#setwd("C:/Users/Domitille/Seafile/projets/METACLOUD/mock_communities/scripts")
#setwd("C:/Users/domit/Seafile/projets/METACLOUD/transcriptomics/mock_communities/scripts")
setwd("C:/Users/djarrige/Desktop/Domitille/projets/Anciens_projets/METACLOUD/scripts/")

Libraries

Variables

vect_COG_category_long <- c("A" = "A: RNA processing and modification",
                            "B" = "B: Chromatin Structure and dynamics",
                            "C" = "C: Energy production and conversion",
                            "D" = "D: Cell cycle control, cell division, chromosome partitioning",
                            "E" = "E: Amino Acid transport and metabolism",
                            "F" = "F: Nucleotide transport and metabolism",
                            "G" = "G: Carbohydrate transport and metabolism",
                            "H" = "H: Coenzyme transport and metabolism",
                            "I" = "I: Lipid transport and metabolism",
                            "J" = "J: Translation, ribosomal structure and biogenesis",
                            "K" = "K: Transcription",
                            "L" = "L: Replication, recombination and repair",
                            "M" = "M: Cell wall/membrane/envelope biogenesis",
                            "N" = "N: Cell motility",
                            "O" = "O: Post-translational modification, protein turnover, chaperones",
                            "P" = "P: Inorganic ion transport and metabolism",
                            "Q" = "Q: Secondary metabolites biosynthesis, transport and catabolism",
                            "T" = "T: Signal Transduction mechanisms",
                            "U" = "U: Intracellular trafficking, secretion and vesicular transport",
                            "V" = "V: Defense mechanisms",
                            "W" = "W: Extracellular structures",
                            "X" = "X: Mobilome: prophages, transposons",
                            "Y" = "Y: Nuclear structure",
                            "Z" = "Z: Cytoskeleton",
                            "R" = "R: General functional prediction only",
                            "S" = "S: Function unknown" #,
                            # "-" = "-: Other"
                            )


COG_colours <- hue_pal()(length(vect_COG_category_long))
names(COG_colours) <- vect_COG_category_long

species_colours <- c("D.hungarica" = "#e66101", "P.graminis" = "#fdb863", 
                     "P.syringae" = "#b2abd2", "R.enclensis" = "#5e3c99")

Functions

compute_deseq2_analysis = function(myData, sample_data, subset_var=FALSE, select=FALSE, 
                                   contrast_col, ref, tested){
  data <- myData
  sample <- sample_data
  if ((subset_var != FALSE) & (select != FALSE)){
    sample %>% filter(!!as.name(subset_var) == select) -> sample
  }
  
  sample[[contrast_col]] <- factor(sample[[contrast_col]])
  data <- data[row.names(sample)]
  
  data_matrix <- round(as.matrix(data))
  d = formula(paste("~", " ", contrast_col))
  
  dds <- DESeqDataSetFromMatrix(countData = data_matrix, 
                                colData = sample,
                                design = d)
  dds <- estimateSizeFactors(dds)
  dds <- DESeq(dds)
  resultsNames(dds)
  resDESeq <- results(dds, contrast = c(contrast_col, tested, ref),
                      independentFiltering = TRUE, alpha=0.1)
  
  resDESeq <- resDESeq[order(resDESeq$padj),]
  res <- data.frame(resDESeq)
  res$gene = row.names(res)
  res$condition = select
  res$SAMPLE_COMPARISON = paste0(tested, "_VS_", ref) 
  #res %>% filter(padj < 0.2 & abs(log2FoldChange) > 1) -> res
  
  return(res)
}

Experimental setup

Comparison of an artificial microbial community gene expression under two cloud-like conditions:

  • summer day (SD): light, 250µM H2O2, 17°C

  • winter night (WN): dark, no added H2O2, 5°C

Bioinformatic workflow and mapping overview

The metatranscriptomics data was processed using a custom made Snakemake workflow.

Two sequencing runs were performed by Genoscreen (Lille, France) as the first run produced relatively low quality reads. Both runs are added into a single dataset in our analyses.

After quality control steps and read cleaning (report) remaining rRNA (not depleted prior to sequencing) were removed with sortmeRNA. As fungal rRNA were not depleted in our libraries, the vast majority of our reads correspond to Dioszegia hungarica rRNAs.

Non ribosomal and ribosomal RNAs were then mapped separately on our reference genomes using STAR.

For non rRNA reads: ~90-95% of reads mapped in biological samples (summary. In blank samples, a larger fraction of reads are unmapped.

Few reads are mapped on P. graminis PDD-13b-3 genome. It will be difficult to get significant results for this species.

Lastly, for each gene of the community, read counts were obtained with featureCounts.’-M’ and ‘–fraction’ options were used to count multi-mapping reads fractionally (if a read maps on x features: each feature gets 1/x counts).

Analyses

Load counts and annotation data
counts_table <- read.csv("../results/all_counts_community_artificial_no_rRNA.tsv", sep = "\t", row.names = "Geneid")

metadata_table <- read.csv("../data/metadata.txt", sep = "\t", row.names = "name") # row.names = "sample"


counts_table %>% rename("WN_TF_1" = "S_5C1", 
                        "WN_TF_2" = "S_5C2", 
                        "WN_TF_3" = "S_5C3",
                        "WN_BLK" = "S_5BLK",
                        "SD_TF_1" = "S_17C1", 
                        "SD_TF_2" = "S_17C2", 
                        "SD_TF_3" = "S_17C3",
                        "SD_BLK" = "S_17BLK") -> counts_table

annotation_table <- read.csv("../data/annotations_final_community_updated.tsv", sep="\t", row.names = "Geneid")
annotation_all <- read.csv("../data/annotations_final_community_updated.tsv", sep="\t", row.names = "Geneid")
annotation_table_long <- read.csv("../data/annotations_final_community_long.tsv", sep="\t", row.names = "Geneid")

## added july 2024
counts_table <- counts_table[intersect(rownames(counts_table), rownames(annotation_all)),]



annotation_diohu <- read.csv("../data/dioszegia_kegg.tsv", sep="\t", row.names = "Geneid")
annotation_psegr <- read.csv("../data/pseudomonas_graminis_kegg.tsv", sep="\t", row.names = "Geneid")
annotation_psesy <- read.csv("../data/pseudomonas_syringae_kegg.tsv", sep="\t", row.names = "Geneid")
annotation_rhoen <- read.csv("../data/rhodococcus_kegg.tsv", sep="\t", row.names = "Geneid")

chem_data_metaT <- read.csv("../data/formaldehyde_evolution_transcriptomics.txt", sep="\t")
chem_data_metaB <- read.csv("../data/formaldehyde_evolution_metabolomics.txt", sep="\t")

## Data for figure

annotation_table_fig <- readxl::read_excel("../data/Table_S3_DEGs_annotations.xlsx")
rename(annotation_table_fig, "COG_category" = "COG category", 
       "COG_category_long" = "COG category long",
       "COG_process" = "COG process") -> annotation_table_fig

metabolomics_df <- read.csv("../data/metabolomics.txt", sep="\t", row.names = 1)

# keep a version of the metabolomics dataset with all time points
metabolomics_df -> metabolomics_all_times_df
metabolomics_all_times_df %>% t() %>% data.frame() -> metabolomics_all_times_df

metabolomics_all_times_df %>% rename("WN_T0_1" = "S5C_T0_1", 
                                     "WN_T0_2" = "S5C_T0_2", 
                                     "WN_T0_3" = "S5C_T0_3",
                                     "SD_T0_1" = "S17C_T0_1", 
                                     "SD_T0_2" = "S17C_T0_2", 
                                     "SD_T0_3" = "S17C_T0_3",
                                     "WN_TF_1" = "S5C_TF_1", 
                                     "WN_TF_2" = "S5C_TF_2", 
                                     "WN_TF_3" = "S5C_TF_3",
                                     "SD_TF_1" = "S17C_TF_1", 
                                     "SD_TF_2" = "S17C_TF_2", 
                                     "SD_TF_3" = "S17C_TF_3") -> metabolomics_all_times_df

metabolomics_all_times_df <- metabolomics_all_times_df[,c("WN_T0_1", "WN_T0_2", "WN_T0_3", "SD_T0_1", "SD_T0_2", "SD_T0_3",
                                                          "WN_TF_1", "WN_TF_2", "WN_TF_3", "SD_TF_1", "SD_TF_2", "SD_TF_3")]

metadata_table_metaB_all_times <- read.csv("../data/metadata_metaB.txt", sep = "\t", row.names = "name") # row.names = "sample"

# Keep final time points only, like for metatranscriptomics
metabolomics_df  %>% t() %>% 
  data.frame() %>% select(starts_with(c("S17C_TF_", "S5C_TF_"))) -> metabolomics_df


metabolomics_df %>% rename("WN_TF_1" = "S5C_TF_1", 
                           "WN_TF_2" = "S5C_TF_2", 
                           "WN_TF_3" = "S5C_TF_3",
                           "SD_TF_1" = "S17C_TF_1", 
                           "SD_TF_2" = "S17C_TF_2", 
                           "SD_TF_3" = "S17C_TF_3") -> metabolomics_df

metabolomics_box_plot_df <- readxl::read_excel("../results/metabolomics_annotation_boxplot.xlsx")

metabolomics_annotations <- readxl::read_excel("../results/Table_S2_Metabolites_identified.xlsx", n_max = 25)
Removal of blank samples
counts_table <- counts_table[,c("WN_TF_1", "WN_TF_2", "WN_TF_3", "SD_TF_1", "SD_TF_2", "SD_TF_3")]
metadata_table <- metadata_table[c("WN_TF_1", "WN_TF_2", "WN_TF_3", "SD_TF_1", "SD_TF_2", "SD_TF_3"),]

Chemical properties of the samples

Formaldehyde evolution

chem_data_metaT$experiment <- "metaT"
chem_data_metaB$experiment <- "metaB"

chem_data <- rbind(chem_data_metaT, chem_data_metaB)



## Metatranscriptomics data

chem_data[chem_data$color == "#89DDF8" & chem_data$experiment == "metaT",] -> tmp1
group_by(tmp1, sampling_time) %>% summarise(formaldehyde_mean=mean(formaldehyde_ratio_to_initial), 
                                            formaldehyde_sd=sd(formaldehyde_ratio_to_initial)) -> tmp1
tmp1$color <- "#89DDF8"
tmp1$condition <- "WN"
tmp1$category <- "biotic_WN"
tmp1$experiment <- "metaT"

chem_data[chem_data$color == "#F8AD18" & chem_data$experiment == "metaT",] -> tmp2
group_by(tmp2, sampling_time) %>% summarise(formaldehyde_mean=mean(formaldehyde_ratio_to_initial), 
                                            formaldehyde_sd=sd(formaldehyde_ratio_to_initial)) -> tmp2
tmp2$color <- "#F8AD18"
tmp2$condition <- "SD"
tmp2$category <- "biotic_SD"
tmp2$experiment <- "metaT"

chem_data[chem_data$color == "#A6C1CA" & chem_data$experiment == "metaT",] -> tmp3
group_by(tmp3, sampling_time) %>% summarise(formaldehyde_mean=mean(formaldehyde_ratio_to_initial), 
                                            formaldehyde_sd=sd(formaldehyde_ratio_to_initial)) -> tmp3
tmp3$color <- "#A6C1CA"
tmp3$condition <- "WN"
tmp3$category <- "abiotic_WN"
tmp3$experiment <- "metaT"

chem_data[chem_data$color == "#C4B69B" & chem_data$experiment == "metaT",] -> tmp4
group_by(tmp4, sampling_time) %>% summarise(formaldehyde_mean=mean(formaldehyde_ratio_to_initial), 
                                            formaldehyde_sd=sd(formaldehyde_ratio_to_initial)) -> tmp4
tmp4$color <- "#C4B69B"
tmp4$condition <- "SD"
tmp4$category <- "abiotic_SD"
tmp4$experiment <- "metaT"

## Metabolomics data

chem_data[chem_data$color == "#89DDF8" & chem_data$experiment == "metaB",] -> tmp5
group_by(tmp5, sampling_time) %>% summarise(formaldehyde_mean=mean(formaldehyde_ratio_to_initial), 
                                            formaldehyde_sd=sd(formaldehyde_ratio_to_initial)) -> tmp5
tmp5$color <- "#89DDF8"
tmp5$condition <- "WN"
tmp5$category <- "biotic_WN"
tmp5$experiment <- "metaB"

chem_data[chem_data$color == "#F8AD18" & chem_data$experiment == "metaB",] -> tmp6
group_by(tmp6, sampling_time) %>% summarise(formaldehyde_mean=mean(formaldehyde_ratio_to_initial), 
                                            formaldehyde_sd=sd(formaldehyde_ratio_to_initial)) -> tmp6
tmp6$color <- "#F8AD18"
tmp6$condition <- "SD"
tmp6$category <- "biotic_SD"
tmp6$experiment <- "metaB"

chem_data[chem_data$color == "#A6C1CA" & chem_data$experiment == "metaB",] -> tmp7
group_by(tmp7, sampling_time) %>% summarise(formaldehyde_mean=mean(formaldehyde_ratio_to_initial), 
                                            formaldehyde_sd=sd(formaldehyde_ratio_to_initial)) -> tmp7
tmp7$color <- "#A6C1CA"
tmp7$condition <- "WN"
tmp7$category <- "abiotic_WN"
tmp7$experiment <- "metaB"

chem_data[chem_data$color == "#C4B69B" & chem_data$experiment == "metaB",] -> tmp8
group_by(tmp8, sampling_time) %>% summarise(formaldehyde_mean=mean(formaldehyde_ratio_to_initial), 
                                            formaldehyde_sd=sd(formaldehyde_ratio_to_initial)) -> tmp8
tmp8$color <- "#C4B69B"
tmp8$condition <- "SD"
tmp8$category <- "abiotic_SD"
tmp8$experiment <- "metaB"


## Merge data

line_data <- rbind(tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8)
rm(tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8)


## Test difference between biotic and abiotic


kruskal_formaldehyde <- c("",
                          try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
                                                                     chem_data_metaB$color == "#F8AD18"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
                                                                     chem_data_metaB$color == "#C4B69B"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
                          try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
                                                                     chem_data_metaB$color == "#F8AD18"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
                                                                     chem_data_metaB$color == "#C4B69B"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
                                                                     chem_data_metaB$color == "#F8AD18"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
                                                                     chem_data_metaB$color == "#C4B69B"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          "",
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
                                                                     chem_data_metaT$color == "#F8AD18"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
                                                                     chem_data_metaT$color == "#C4B69B"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
                                                                     chem_data_metaT$color == "#F8AD18"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
                                                                     chem_data_metaT$color == "#C4B69B"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
                                                                     chem_data_metaT$color == "#F8AD18"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
                                                                     chem_data_metaT$color == "#C4B69B"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
                                                                     chem_data_metaT$color == "#F8AD18"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
                                                                     chem_data_metaT$color == "#C4B69B"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          "",
                          try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
                                                                     chem_data_metaB$color == "#89DDF8"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
                                                                     chem_data_metaB$color == "#A6C1CA"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_WN", 3), rep("abiotic_WN", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
                          try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
                                                                     chem_data_metaB$color == "#89DDF8"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
                                                                     chem_data_metaB$color == "#A6C1CA"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_WN", 3), rep("abiotic_WN", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
                                                                     chem_data_metaB$color == "#89DDF8"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
                                                                     chem_data_metaB$color == "#A6C1CA"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_WN", 3), rep("abiotic_WN", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          "",
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
                                                                     chem_data_metaT$color == "#89DDF8"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
                                                                     chem_data_metaT$color == "#A6C1CA"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_WN", 3), rep("abiotic_WN", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
                                                                     chem_data_metaT$color == "#89DDF8"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
                                                                     chem_data_metaT$color == "#A6C1CA"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_WN", 3), rep("abiotic_WN", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
                                                                     chem_data_metaT$color == "#89DDF8"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
                                                                     chem_data_metaT$color == "#A6C1CA"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_WN", 3), rep("abiotic_WN", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
                                                                     chem_data_metaT$color == "#89DDF8"),
                                                                    "formaldehyde_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
                                                                     chem_data_metaT$color == "#A6C1CA"),
                                                                    "formaldehyde_ratio_to_initial"]),
                                              g = c(rep("biotic_WN", 3), rep("abiotic_WN", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE)
)

## Test difference between time 0 an the other time points

# kruskal_formaldehyde <- c("",
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
#                                                             chem_data_metaB$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_SD_TF_1", 3), rep("biotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
#                                                             chem_data_metaB$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_SD_TF_2", 3), rep("biotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
#                                                             chem_data_metaB$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_SD_TF_3", 3), rep("biotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       "",
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
#                                                             chem_data_metaT$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_SD_TF_1", 3), rep("biotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
#                                                             chem_data_metaT$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_SD_TF_2", 3), rep("biotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
#                                                             chem_data_metaT$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_SD_TF_3", 3), rep("biotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
#                                                             chem_data_metaT$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#F8AD18"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_SD_5", 3), rep("biotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       "",
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
#                                                             chem_data_metaB$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_WN_TF_1", 3), rep("biotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
#                                                             chem_data_metaB$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_WN_TF_2", 3), rep("biotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
#                                                             chem_data_metaB$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_WN_TF_3", 3), rep("biotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       "",
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
#                                                             chem_data_metaT$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_WN_TF_1", 3), rep("biotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
#                                                             chem_data_metaT$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_WN_TF_2", 3), rep("biotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
#                                                             chem_data_metaT$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_WN_TF_3", 3), rep("biotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
#                                                             chem_data_metaT$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#89DDF8"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("biotic_WN_5", 3), rep("biotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE)
#                      )

kruskal_df <- data.frame(time = rep(c(0, 1, 2, 3, 0, 1, 2, 3, 5), 2),
                         height = rep(0, 18),
                         experiment = rep(c(rep("metaB", 4), rep("metaT", 5)), 2),
                         condition = c(rep("SD", 9), rep("WN", 9)),
                         category = c(rep("community SD", 9), rep("community WN", 9)),
                         color = c(rep("#F8AD18", 9), rep("#89DDF8", 9)),
                         pvalue = kruskal_formaldehyde)



# kruskal_formaldehyde_abio <- c("",
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_1", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_2", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_3", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       "",
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_1", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_2", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_3", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_5", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       "",
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
#                                                             chem_data_metaB$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_WN_TF_1", 3), rep("abiotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
#                                                             chem_data_metaB$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_WN_TF_2", 3), rep("abiotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
#                                                             chem_data_metaB$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_WN_TF_3", 3), rep("abiotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       "",
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
#                                                             chem_data_metaT$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_WN_TF_1", 3), rep("abiotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
#                                                             chem_data_metaT$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_WN_TF_2", 3), rep("abiotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
#                                                             chem_data_metaT$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_WN_TF_3", 3), rep("abiotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
#                                                             chem_data_metaT$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#A6C1CA"),
#                                                            "formaldehyde_ratio_to_initial"]),
#                                      g = c(rep("abiotic_WN_5", 3), rep("abiotic_WN_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE)
#                      )

# kruskal_df_abio <- data.frame(time = rep(c(0, 1, 2, 3, 0, 1, 2, 3, 5), 2),
#                          height = rep(1.15, 18),
#                          experiment = rep(c(rep("metaB", 4), rep("metaT", 5)), 2),
#                          condition = c(rep("SD", 9), rep("WN", 9)),
#                          category = c(rep("abiotic SD", 9), rep("abiotic WN", 9)),
#                          color = c(rep("#C4B69B", 9), rep("#A6C1CA", 9)),
#                          pvalue = kruskal_formaldehyde_abio)


#krusk <- rbind(kruskal_df, kruskal_df_abio)
krusk <- kruskal_df


## Segment data for sampling time

segment_data <- data.frame(x = c(4, 0, 3.5), xend = c(4, 0, 3.5), 
                           y = c(-Inf, -Inf, -Inf), yend = c(Inf, Inf, Inf),
                           experiment = c("metaT", "metaB", "metaB"))
  
chem_data %>% ggplot() +
  geom_point(aes(x=sampling_time, y=formaldehyde_ratio_to_initial, color=color)) +
  ylim(c(-0.1, 1.2)) +
  xlim(c(0, 5)) +
  scale_colour_identity("category", labels = c("community WN", "abiotic WN",
                                               "abiotic SD", "community SD"), 
                        guide="legend") +
  scale_fill_identity() +
  ylab(label = "Relative formaldehyde evolution") +
  xlab(label = "Incubation time (h)") +
  # facet_grid(rows = vars(experiment), cols = vars(condition)) + #, nrow=2, ncol=2
  facet_grid(rows = vars(condition), cols = vars(experiment),
             labeller = as_labeller(c("metaT" = "Metatranscriptomics", 
                                      "metaB" = "Meta-metabolomics",
                                      "SD" = "SD",
                                      "WN" = "WN"))) + 
  theme(legend.position = "bottom",
        panel.background = element_rect(fill="#f4f4f4")) +
  
  
  geom_path(data = line_data[line_data$category == "biotic_SD",], 
            aes(x = sampling_time, y = formaldehyde_mean, color = color), 
            linewidth = 1) + 
  geom_ribbon(data = line_data[line_data$category == "biotic_SD",], 
              aes(x = sampling_time, 
                  ymin = formaldehyde_mean - formaldehyde_sd,
                  ymax = formaldehyde_mean + formaldehyde_sd,
                  fill = color), alpha=0.25, linewidth=0.05) +
  
  geom_path(data = line_data[line_data$category == "abiotic_SD",], 
            aes(x = sampling_time, y = formaldehyde_mean, color = color), 
            linewidth = 1) + 
  geom_ribbon(data = line_data[line_data$category == "abiotic_SD",], 
              aes(x = sampling_time, 
                  ymin = formaldehyde_mean - formaldehyde_sd,
                  ymax = formaldehyde_mean + formaldehyde_sd,
                  fill = color), alpha=0.25, linewidth=0.05) +
  
  geom_path(data = line_data[line_data$category == "biotic_WN",], 
            aes(x = sampling_time, y = formaldehyde_mean, color = color), 
            linewidth = 1) + 
  geom_ribbon(data = line_data[line_data$category == "biotic_WN",], 
              aes(x = sampling_time, 
                  ymin = formaldehyde_mean - formaldehyde_sd,
                  ymax = formaldehyde_mean + formaldehyde_sd,
                  fill = color), alpha=0.25, linewidth=0.05) + 
  
  geom_path(data = line_data[line_data$category == "abiotic_WN",], 
            aes(x = sampling_time, y = formaldehyde_mean, color = color), 
            linewidth = 1) + 
  geom_ribbon(data = line_data[line_data$category == "abiotic_WN",], 
              aes(x = sampling_time, 
                  ymin = formaldehyde_mean - formaldehyde_sd,
                  ymax = formaldehyde_mean + formaldehyde_sd,
                  fill = color), alpha=0.25, linewidth=0.05) + 
  
  # plot significance stars
  geom_text(data=krusk[krusk$category == "community SD",], 
            aes(x = time, y = height, label = pvalue, colour=color), 
            size = 7, show.legend = FALSE, nudge_y = -0.07) +
  geom_text(data=krusk[krusk$category == "community WN",], 
            aes(x = time, y = height, label = pvalue, colour=color), 
            size = 7, show.legend = FALSE, nudge_y = -0.07) +
  geom_text(data=krusk[krusk$category == "abiotic SD",],
            aes(x = time, y = height, label = pvalue, colour=color),
            size = 7, show.legend = FALSE) +
  geom_text(data=krusk[krusk$category == "abiotic WN",],
            aes(x = time, y = height, label = pvalue, colour=color),
            size = 7, show.legend = FALSE) +
  
  # geom_segment(aes(x=4, xend=4, y=-Inf, yend=Inf)) +
  geom_segment(data=segment_data, aes(x = x, xend = xend, y = y, yend = yend)) +
  geom_text(data=segment_data, aes(x = x + 0.2, y = 0.20, label = "cell sampling"), angle=90, size=3) -> plot

print(plot)

ggsave(plot = plot, filename = "../figures/formaldehyde_evolution.tiff", dpi = 300, width = 10, height = 6, bg="white")

H2O2 evolution

chem_data_metaT$experiment <- "metaT"
chem_data_metaB$experiment <- "metaB"

chem_data <- rbind(chem_data_metaT, chem_data_metaB)



## Metatranscriptomics data



chem_data[chem_data$color == "#F8AD18" & chem_data$experiment == "metaT",] -> tmp2
group_by(tmp2, sampling_time) %>% summarise(H2O2_mean=mean(H2O2_ratio_to_initial), 
                                            H2O2_sd=sd(H2O2_ratio_to_initial)) -> tmp2
tmp2$color <- "#F8AD18"
tmp2$condition <- "SD"
tmp2$category <- "biotic_SD"
tmp2$experiment <- "metaT"


chem_data[chem_data$color == "#C4B69B" & chem_data$experiment == "metaT",] -> tmp4
group_by(tmp4, sampling_time) %>% summarise(H2O2_mean=mean(H2O2_ratio_to_initial), 
                                            H2O2_sd=sd(H2O2_ratio_to_initial)) -> tmp4
tmp4$color <- "#C4B69B"
tmp4$condition <- "SD"
tmp4$category <- "abiotic_SD"
tmp4$experiment <- "metaT"

## Metabolomics data


chem_data[chem_data$color == "#F8AD18" & chem_data$experiment == "metaB",] -> tmp6
group_by(tmp6, sampling_time) %>% summarise(H2O2_mean=mean(H2O2_ratio_to_initial), 
                                            H2O2_sd=sd(H2O2_ratio_to_initial)) -> tmp6
tmp6$color <- "#F8AD18"
tmp6$condition <- "SD"
tmp6$category <- "biotic_SD"
tmp6$experiment <- "metaB"


chem_data[chem_data$color == "#C4B69B" & chem_data$experiment == "metaB",] -> tmp8
group_by(tmp8, sampling_time) %>% summarise(H2O2_mean=mean(H2O2_ratio_to_initial), 
                                            H2O2_sd=sd(H2O2_ratio_to_initial)) -> tmp8
tmp8$color <- "#C4B69B"
tmp8$condition <- "SD"
tmp8$category <- "abiotic_SD"
tmp8$experiment <- "metaB"


## Merge data

line_data <- rbind(tmp2, tmp4, tmp6, tmp8)
rm(tmp2, tmp4, tmp6, tmp8)

## Test difference between time 0 an the other time points

kruskal_h2o2 <-  c("",
                          try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
                                                                     chem_data_metaB$color == "#F8AD18"),
                                                                    "H2O2_ratio_to_initial"],
                                                    chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
                                                                     chem_data_metaB$color == "#C4B69B"),
                                                                    "H2O2_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
                          try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
                                                                     chem_data_metaB$color == "#F8AD18"),
                                                                    "H2O2_ratio_to_initial"],
                                                    chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
                                                                     chem_data_metaB$color == "#C4B69B"),
                                                                    "H2O2_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
                                                                     chem_data_metaB$color == "#F8AD18"),
                                                                    "H2O2_ratio_to_initial"],
                                                    chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
                                                                     chem_data_metaB$color == "#C4B69B"),
                                                                    "H2O2_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          "",
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
                                                                     chem_data_metaT$color == "#F8AD18"),
                                                                    "H2O2_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
                                                                     chem_data_metaT$color == "#C4B69B"),
                                                                    "H2O2_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
                                                                     chem_data_metaT$color == "#F8AD18"),
                                                                    "H2O2_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
                                                                     chem_data_metaT$color == "#C4B69B"),
                                                                    "H2O2_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
                                                                     chem_data_metaT$color == "#F8AD18"),
                                                                    "H2O2_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
                                                                     chem_data_metaT$color == "#C4B69B"),
                                                                    "H2O2_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
                          try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
                                                                     chem_data_metaT$color == "#F8AD18"),
                                                                    "H2O2_ratio_to_initial"],
                                                    chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
                                                                     chem_data_metaT$color == "#C4B69B"),
                                                                    "H2O2_ratio_to_initial"]),
                                              g = c(rep("biotic_SD", 3), rep("abiotic_SD", 3))
                          )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE)
                     )

kruskal_df <- data.frame(time = c(0, 1, 2, 3, 0, 1, 2, 3, 5),
                         height = rep(0, 9),
                         experiment = c(rep("metaB", 4), rep("metaT", 5)),
                         condition = rep("SD", 9),
                         category = rep("community SD", 9),
                         color = rep("#F8AD18", 9),
                         pvalue = kruskal_h2o2)

# 
# kruskal_h2o2_abio <- c("",
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 1 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_1", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 2 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_2", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaB[(chem_data_metaB$sampling_time == 3 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"],
#                                            chem_data_metaB[(chem_data_metaB$sampling_time == 0 &
#                                                             chem_data_metaB$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_3", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       "",
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 1 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_1", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE) ,
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 2 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_2", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 3 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_TF_3", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE),
#                       try(if(kruskal.test(x = c(chem_data_metaT[(chem_data_metaT$sampling_time == 5 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"],
#                                            chem_data_metaT[(chem_data_metaT$sampling_time == 0 &
#                                                             chem_data_metaT$color == "#C4B69B"),
#                                                            "H2O2_ratio_to_initial"]),
#                                      g = c(rep("abiotic_SD_5", 3), rep("abiotic_SD_0", 3))
#                       )[["p.value"]] < 0.05){"*"}else{""}, silent = TRUE)
#                      )

# kruskal_df_abio <- data.frame(time = c(0, 1, 2, 3, 0, 1, 2, 3, 5),
#                          height = rep(1.15, 9),
#                          experiment = c(rep("metaB", 4), rep("metaT", 5)),
#                          condition = rep("SD", 9),
#                          category = rep("abiotic SD", 9),
#                          color = rep("#C4B69B", 9),
#                          pvalue = kruskal_h2o2_abio)


# krusk <- rbind(kruskal_df, kruskal_df_abio)
krusk <- kruskal_df


## Segment data for sampling time

segment_data <- data.frame(x = c(4, 0, 3.5), xend = c(4, 0, 3.5), 
                           y = c(-Inf, -Inf, -Inf), yend = c(Inf, Inf, Inf),
                           experiment = c("metaT", "metaB", "metaB"))
  
chem_data[chem_data$condition == "SD",] %>% ggplot() +
  geom_point(aes(x=sampling_time, y=H2O2_ratio_to_initial, color=color)) +
  ylim(c(-0.1, 1.2)) +
  xlim(c(0, 5)) +
  scale_colour_identity("category", labels = c("abiotic SD", "community SD"), 
                        guide="legend") +
  scale_fill_identity() +
  ylab(label = "Relative H2O2 evolution") +
  xlab(label = "Incubation time (h)") +
  # facet_grid(rows = vars(experiment), cols = vars(condition)) + #, nrow=2, ncol=2
  facet_grid(rows = vars(condition), cols = vars(experiment),
             labeller = as_labeller(c("metaT" = "Metatranscriptomics", 
                                      "metaB" = "Meta-metabolomics",
                                      "SD" = "SD",
                                      "WN" = "WN"))) + 
  theme(legend.position = "bottom",
        panel.background = element_rect(fill="#f4f4f4")) +
  
  
  geom_path(data = line_data[line_data$category == "biotic_SD",], 
            aes(x = sampling_time,y =H2O2_mean, color = color), 
            linewidth = 1) + 
  geom_ribbon(data = line_data[line_data$category == "biotic_SD",], 
              aes(x = sampling_time, 
                  ymin = H2O2_mean - H2O2_sd,
                  ymax = H2O2_mean + H2O2_sd,
                  fill = color), alpha=0.25, linewidth=0.05) +
  
    geom_path(data = line_data[line_data$category == "abiotic_SD",], 
            aes(x = sampling_time,y =H2O2_mean, color = color), 
            linewidth = 1) + 
  geom_ribbon(data = line_data[line_data$category == "abiotic_SD",], 
              aes(x = sampling_time, 
                  ymin = H2O2_mean - H2O2_sd,
                  ymax = H2O2_mean + H2O2_sd,
                  fill = color), alpha=0.25, linewidth=0.05) +
  
  # plot significance stars
  geom_text(data=krusk[krusk$category == "community SD",], 
            aes(x = time, y = height, label = pvalue, colour=color), 
            size = 7, show.legend = FALSE, nudge_y = -0.07) +
  geom_text(data=krusk[krusk$category == "abiotic SD",],
            aes(x = time, y = height, label = pvalue, colour=color),
            size = 7, show.legend = FALSE) +

  
  # geom_segment(aes(x=4, xend=4, y=-Inf, yend=Inf)) +
  geom_segment(data=segment_data, aes(x = x, xend = xend, y = y, yend = yend)) +
  geom_segment(aes(x = -Inf, xend = Inf, y = 0.2, yend = 0.2), colour = "darkred", linetype = 2) +
  geom_text(data=segment_data, aes(x = x + 0.2, y = 0.42, label = "cell sampling"), angle=90, size=3) -> plot

print(plot)

ggsave(plot = plot, filename = "../figures/H2O2_evolution.tiff", dpi = 300, width = 10, height = 3.6, bg="white")

Descriptive statistics on complete community metatranscriptomics and metabolomics data

Metatranscriptomics

Sample-wise statistics (raw metatranscriptomics counts)

message("Computing sample-wise statistics on raw counts")
sample_stat_prenorm <- data.frame(
  mean = apply(counts_table, 2, mean, na.rm = TRUE),
  sd = apply(counts_table, 2, sd, na.rm = TRUE),
  iqr = apply(counts_table, 2, IQR, na.rm = TRUE),
  Q1 = apply(counts_table, 2, quantile, p = 0.25, na.rm = TRUE),
  median = apply(counts_table, 2, median, na.rm = TRUE),
  Q3 = apply(counts_table, 2, quantile, p = 0.75, na.rm = TRUE),
  max = apply(counts_table, 2, max, na.rm = TRUE),
  null = apply(counts_table == 0, 2, sum, na.rm = TRUE)
)

kable(sample_stat_prenorm[0:6, ], caption = "Sample-wise statistics before normalisation")
Sample-wise statistics before normalisation
mean sd iqr Q1 median Q3 max null
WN_TF_1 2.0060345 80.05179 0.25 0 0 0.25 8701.91 19221
WN_TF_2 1.5756311 73.84748 0.00 0 0 0.00 6777.67 21357
WN_TF_3 2.0505394 80.69807 0.25 0 0 0.25 8361.50 19078
SD_TF_1 2.0047102 100.27988 0.00 0 0 0.00 10856.58 21708
SD_TF_2 0.8727698 44.34895 0.00 0 0 0.00 4582.83 23410
SD_TF_3 2.8208445 148.89023 0.00 0 0 0.00 14318.75 22215

Gene-wise statistics (raw metatranscriptomics counts)

message("Computing gene-wise statistics on raw counts")
gene_stat_prenorm <- data.frame(
  mean = apply(counts_table, 1, mean, na.rm = TRUE),
  sd = apply(counts_table, 1, sd, na.rm = TRUE),
  iqr = apply(counts_table, 1, IQR, na.rm = TRUE),
  Q1 = apply(counts_table, 1, quantile, p = 0.25, na.rm = TRUE),
  median = apply(counts_table, 1, median, na.rm = TRUE),
  Q3 = apply(counts_table, 1, quantile, p = 0.75, na.rm = TRUE),
  max = apply(counts_table, 1, max, na.rm = TRUE),
  null = apply(counts_table == 0, 1, sum, na.rm = TRUE)
)

#kable(gene_stat_prenorm[100:109, ], caption = "Gene-wise statistics before normalisation")

Zeroes filtering and smoothing inspired by MTXmodel article (Zhang et al. 2021)

species <- unlist(unique(annotation_table[,"Organism"]))
samples <- row.names(metadata_table)

Gene with 0 counts in more than 70% of samples are deemed unexpressed and are removed from the dataset.

message("Filtering undetected genes")
undetected_genes <- gene_stat_prenorm$null >= ncol(counts_table) * 0.70
print(paste0("Undetected genes (null in >= 70% samples): ", sum(undetected_genes)))

[1] “Undetected genes (null in >= 70% samples): 19262”

kept_genes <- !undetected_genes
print(paste0("Kept genes: ", sum(kept_genes)))

[1] “Kept genes: 7191”

## Genes after filtering
counts_filtered <- counts_table[kept_genes, ]
annotation_table <- annotation_all[rownames(counts_filtered),] #row.names()

## Species abundance (sum of all counts)
totals_df <- data.frame()
for (spe in species) {
  spe_geneid <- annotation_table$Organism == spe
  for (samp in samples) {
    totals_df[spe, samp] <- sum(counts_filtered[spe_geneid, samp], na.rm=TRUE)
  }
}
#################### remove standardisation??? ############
counts_standard <- counts_filtered
table_gene_expr <- counts_table
table_gene_expr$detected <- "No"
table_gene_expr[kept_genes, "detected"] <- "yes"
table_gene_expr <- rownames_to_column(table_gene_expr)
table_gene_expr <- left_join(table_gene_expr, rownames_to_column(annotation_table_long)[,c("rowname", "locus_tag", "transcriptId")])
# write_delim(table_gene_expr, file = "../results/table_of_kept_expressed_genes.tsv", delim = "\t", )
## remaining zeroes smoothing (as in Zhang et al. 2021)

min_val <- apply(counts_standard, 1, function(x) (min(x[x>0])/2))


for (gene in row.names(counts_standard)) {
  counts_standard[gene,][counts_standard[gene,] == 0] <- min_val[gene]
}
message("Computing sample-wise statistics on filtered counts")
sample_stat_filt <- data.frame(
  mean = apply(counts_standard, 2, mean, na.rm = TRUE),
  sd = apply(counts_standard, 2, sd, na.rm = TRUE),
  iqr = apply(counts_standard, 2, IQR, na.rm = TRUE),
  Q1 = apply(counts_standard, 2, quantile, p = 0.25, na.rm = TRUE),
  median = apply(counts_standard, 2, median, na.rm = TRUE),
  Q3 = apply(counts_standard, 2, quantile, p = 0.75, na.rm = TRUE),
  max = apply(counts_standard, 2, max, na.rm = TRUE),
  null = apply(counts_standard == 0, 2, sum, na.rm = TRUE)
)

kable(sample_stat_filt[0:6, ], caption = "Sample-wise statistics after filtering")
Sample-wise statistics after filtering
mean sd iqr Q1 median Q3 max null
WN_TF_1 7.274402 153.42034 1.745 0.250 0.750 1.995 8701.91 0
WN_TF_2 5.798768 141.55673 0.835 0.165 0.330 1.000 6777.67 0
WN_TF_3 7.436439 154.65538 1.670 0.330 0.830 2.000 8361.50 0
SD_TF_1 7.435202 192.23869 0.830 0.170 0.375 1.000 10856.58 0
SD_TF_2 3.346716 85.01516 0.375 0.125 0.250 0.500 4582.83 0
SD_TF_3 10.483380 285.44101 0.700 0.170 0.330 0.870 14318.75 0

CLR (Centered Log ratio) transformation of whole community metatranscriptomics counts

counts_clr <- counts_standard

for (samp in samples) {
  counts_clr[,samp] <- clr(counts_standard[,samp])
}
message("Computing sample-wise statistics on filtered counts")
sample_stat_clr <- data.frame(
  mean = apply(counts_clr, 2, mean, na.rm = TRUE),
  sd = apply(counts_clr, 2, sd, na.rm = TRUE),
  iqr = apply(counts_clr, 2, IQR, na.rm = TRUE),
  Q1 = apply(counts_clr, 2, quantile, p = 0.25, na.rm = TRUE),
  median = apply(counts_clr, 2, median, na.rm = TRUE),
  Q3 = apply(counts_clr, 2, quantile, p = 0.75, na.rm = TRUE),
  max = apply(counts_clr, 2, max, na.rm = TRUE),
  null = apply(counts_clr == 0, 2, sum, na.rm = TRUE)
)

kable(sample_stat_clr[0:6, ], caption = "Sample-wise statistics after CLR transformation")
Sample-wise statistics after CLR transformation
mean sd iqr Q1 median Q3 max null
WN_TF_1 0 1.366662 2.076935 -1.1413059 -0.0426936 0.9356294 9.316286 0
WN_TF_2 0 1.246467 1.801810 -0.9619634 -0.2688162 0.8398464 9.661235 0
WN_TF_3 0 1.357223 1.801810 -0.9519112 -0.0295782 0.8498986 9.188144 0
SD_TF_1 0 1.220095 1.771957 -0.9654242 -0.1742966 0.8065326 10.099059 0
SD_TF_2 0 1.061585 1.386294 -0.8828711 -0.1897239 0.5034233 9.626643 0
SD_TF_3 0 1.204212 1.632695 -0.9117566 -0.2484624 0.7209382 10.429525 0
## Gene-wise statistics after normalisation
message("Computing gene-wise statistics on log-transformed and normalised counts")
gene_stat_norm <- data.frame(mean = apply(counts_clr, 1, mean, na.rm=TRUE),
                             var = apply(counts_clr, 1, var, na.rm=TRUE),
                             sd = apply(counts_clr, 1, sd, na.rm=TRUE),
                             iqr = apply(counts_clr, 1, IQR, na.rm=TRUE),
                             min = apply(counts_clr, 1, min, na.rm=TRUE),
                             med = apply(counts_clr, 1, median, na.rm=TRUE),
                             max = apply(counts_clr, 1, max, na.rm=TRUE))

# Ajout du coefficient de variation
gene_stat_norm$coef_var <- (gene_stat_norm$sd / gene_stat_norm$mean)

Metatranscriptomics counts distribution

par(mfrow=c(1,1))
hist(unlist(counts_table),
     breaks = 200,
     cex.axis = 0.7,
     las = 1,
     col = "skyblue",
     xlab = "raw counts",
     main = "Distribution of raw counts")

par(mfrow=c(1,1))
hist(unlist(counts_clr),
     breaks = 200,
     cex.axis = 0.7,
     las = 1,
     col = "skyblue",
     xlab = "clr-transformed counts",
     main = "Distribution of clr-transformed counts")

The distribution of the whole community metatranscriptomics counts seems close to normal.

# Raw data
boxplot(counts_table,
        main = "Raw expression",
        horizontal = TRUE,
        col = metadata_table$color,
        cex = 0.5,
        cex.axis = 0.8,
        las = 1)

boxplot(counts_clr,
        main = "clr-transformed expression",
        horizontal = TRUE,
        col = metadata_table$color,
        cex = 0.5,
        cex.axis = 0.8,
        las = 1)

The CLR transformation centred our data.

Community metatranscriptomics counts repartition by species

totals_df$species <- row.names((totals_df))
totals_df %>%
    pivot_longer(!species, 
                names_to=c("sample"),
                values_to="total_counts") %>%
  mutate(sample = case_when(sample == "SD_TF_1" ~ "SD_TF_1",
                            sample == "SD_TF_2" ~ "SD_TF_2",
                            sample == "SD_TF_3" ~ "SD_TF_3",
                            sample == "WN_TF_1" ~ "WN_TF_1",
                            sample == "WN_TF_2" ~ "WN_TF_2",
                            sample == "WN_TF_3" ~ "WN_TF_3")) -> totals_df
ggplot(data=totals_df, mapping=aes(x=sample, y=total_counts, fill=species)) + 
  geom_bar(position="fill", stat="identity") + 
  scale_fill_brewer(palette = "PuOr") +
  labs(y = "Percentage of total counts") +
  scale_y_continuous(labels = as_function(~ 100 * .)) + 
  theme(axis.text.x = element_text(colour = c("SD_TF_1" = "darkorange",
                                              "SD_TF_2" = "darkorange",
                                              "SD_TF_3" = "darkorange",
                                              "WN_TF_1" = "darkcyan",
                                              "WN_TF_2" = "darkcyan",
                                              "WN_TF_3" = "darkcyan"))) + 
  ggtitle("Total metatranscriptomics counts per species") -> p 

print(p)

ggsave("../figures/Figure_S3_counts_repartition.png", p, dpi = 300)
ggsave("../figures/Figure_S3_counts_repartition.tiff", p, height = 7, width = 7, dpi = 300)

As previously noted, Dioszegia hungarica counts are largely dominant in our data. Pseudomonas graminis associated counts are very rare.

D. hungarica filtered counts repartition by nucleus or mitochondrial origin
organelle_df <- data.frame()

mito_geneid <- annotation_table$Chr == "Dioszegia_hungarica_PDD-24b-2_contig_35"
nucl_geneid <- (annotation_table$Organism == "D.hungarica" & annotation_table$Chr != "Dioszegia_hungarica_PDD-24b-2_contig_35")

for (samp in samples) {
    organelle_df["mitochondria", samp] <- sum(counts_filtered[mito_geneid, samp], na.rm=TRUE)
    organelle_df["nucleus", samp] <- sum(counts_filtered[nucl_geneid, samp], na.rm=TRUE)
}

organelle_df$organelle <- row.names((organelle_df))
organelle_df %>%
    pivot_longer(!organelle, 
                names_to=c("sample"),
                values_to="total_counts") %>%
  mutate(sample = case_when(sample == "SD_TF_1" ~ "SD_TF_1",
                            sample == "SD_TF_2" ~ "SD_TF_2",
                            sample == "SD_TF_3" ~ "SD_TF_3",
                            sample == "WN_TF_1" ~ "WN_TF_1",
                            sample == "WN_TF_2" ~ "WN_TF_2",
                            sample == "WN_TF_3" ~ "WN_TF_3")) -> organelle_df

ggplot(data=organelle_df, mapping=aes(x=sample, y=total_counts, fill=organelle)) + 
  geom_bar(position="fill", stat="identity") + 
  scale_fill_brewer(palette = "PuOr") +
  labs(y = "Percentage of total counts") +
  scale_y_continuous(labels = as_function(~ 100 * .)) + 
  theme(axis.text.x = element_text(colour = c("SD_TF_1" = "darkorange",
                                              "SD_TF_2" = "darkorange",
                                              "SD_TF_3" = "darkorange",
                                              "WN_TF_1" = "darkcyan",
                                              "WN_TF_2" = "darkcyan",
                                              "WN_TF_3" = "darkcyan"))) + 
  ggtitle("Total transcript counts per D. hungarica compartment") -> p 

print(p)

ggsave("../figures/Diohu_counts_repartition.png", p, dpi = 300)
ggsave("../figures/Diohu_counts_repartition.tiff", p, height = 7, width = 7, dpi = 300)

Among Dioszegia hungarica counts, a large portion come from transcripts produced in the mitochondria, especially in SD conditions.

Metabolomics

Metabolite-wise statistics (raw data)

# message("Computing metabolite-wise statistics on raw counts")

metabolite_stat_prenorm <- data.frame(
  mean = apply(metabolomics_all_times_df, 1, mean, na.rm = TRUE),
  sd = apply(metabolomics_all_times_df, 1, sd, na.rm = TRUE),
  iqr = apply(metabolomics_all_times_df, 1, IQR, na.rm = TRUE),
  Q1 = apply(metabolomics_all_times_df, 1, quantile, p = 0.25, na.rm = TRUE),
  median = apply(metabolomics_all_times_df, 1, median, na.rm = TRUE),
  Q3 = apply(metabolomics_all_times_df, 1, quantile, p = 0.75, na.rm = TRUE),
  max = apply(metabolomics_all_times_df, 1, max, na.rm = TRUE),
  null = apply(metabolomics_all_times_df == 0, 1, sum, na.rm = TRUE)
)

kable(metabolite_stat_prenorm[100:109, ], caption = "Gene-wise statistics before normalisation")
Gene-wise statistics before normalisation
mean sd iqr Q1 median Q3 max null
M227.1754T7.46 0.0297637 0.0125831 0.0153123 0.0216464 0.0248620 0.0369588 0.0545123 0
M227.1756T7.71 0.0009423 0.0005382 0.0005236 0.0006028 0.0008935 0.0011263 0.0023538 0
M229.1547T7.3 0.0002872 0.0000654 0.0001292 0.0002224 0.0002810 0.0003516 0.0003785 0
M229.1548T7.51 0.0002844 0.0000405 0.0000395 0.0002643 0.0002889 0.0003038 0.0003452 0
M231.1704T7.41 0.0007549 0.0004071 0.0004789 0.0004242 0.0006295 0.0009030 0.0015536 0
M231.1704T7.7 0.0007458 0.0003289 0.0004379 0.0004945 0.0007700 0.0009324 0.0013820 0
M231.1705T8.71 0.0001531 0.0000906 0.0001410 0.0000854 0.0001604 0.0002264 0.0002715 0
M232.1544T7.21 0.0019758 0.0016928 0.0009050 0.0010000 0.0011673 0.0019050 0.0056565 0
M232.1544T7.07 0.0010623 0.0005972 0.0005553 0.0006736 0.0007847 0.0012289 0.0021863 0
M233.0592T7.35 0.0000623 0.0000277 0.0000356 0.0000442 0.0000653 0.0000798 0.0001143 0

Zero filtering and smoothing metabolomics

Metabolites with 0 counts in more than 70% of samples are deemed unexpressed and are removed from the dataset.

message("Filtering undetected metabolites")
undetected_metabolites <- metabolite_stat_prenorm$null >= ncol(metabolomics_all_times_df) * 0.70
print(paste0("undetected_metabolites (null in >= 70% samples): ", sum(undetected_metabolites)))

[1] “undetected_metabolites (null in >= 70% samples): 5”

kept_metabolites <- !undetected_metabolites
print(paste0("Kept metabolites: ", sum(kept_metabolites)))

[1] “Kept metabolites: 465”

## metabolites after filtering
metabolomics_all_times_filtered <- metabolomics_all_times_df[kept_metabolites, ]
## remaining zeroes smoothing (as in Zhang et al. 2021)

min_val <- apply(metabolomics_all_times_filtered, 1, function(x) (min(x[x>0])/2))


for (metabolite in row.names(metabolomics_all_times_filtered)) {
  metabolomics_all_times_filtered[metabolite,][metabolomics_all_times_filtered[metabolite,] == 0] <- min_val[metabolite]
}

CLR transformation metabolomics

metabolomics_all_times_clr <- metabolomics_all_times_filtered

for (samp in names(metabolomics_all_times_filtered )){
  metabolomics_all_times_clr[,samp] <- as.vector(clr(metabolomics_all_times_filtered[,samp]))
}

Metabolomics data repartition

par(mfrow=c(1,1))
hist(unlist(metabolomics_all_times_df),
     breaks = 200,
     cex.axis = 0.7,
     las = 1,
     col = "skyblue",
     xlab = "raw metabolomics data",
     main = "Distribution of raw metabolomics data")

par(mfrow=c(1,1))
hist(unlist(metabolomics_all_times_clr),
     breaks = 200,
     cex.axis = 0.7,
     las = 1,
     col = "skyblue",
     xlab = "clr-transformed metabolomics data, all times",
     main = "Distribution of clr-transformed metabolomics data, all times")

The distribution of metabolomics data is close to normal.

boxplot(metabolomics_all_times_df,
        main = "metabolomics raw data",
        horizontal = TRUE,
        col = metadata_table_metaB_all_times$color,
        cex = 0.5,
        cex.axis = 0.8,
        las = 1)

boxplot(metabolomics_all_times_clr,
        main = "metabolomics clr-transformed expression",
        horizontal = TRUE,
        col = metadata_table_metaB_all_times$color,
        cex = 0.5,
        cex.axis = 0.8,
        las = 1)

The CLR transformation centred our data.

Exploratory statistical analyses of the whole community

Principal Component Analyses (PCA) metatranscriptomic

par(mfrow = c(2,2))
res_pca <- PCA(t(counts_clr), scale.unit = TRUE, graph = FALSE)
counts_data <- t(counts_clr)
metadata_tmp <- data.frame(metadata_table, stringsAsFactors = TRUE)
permanova <- adonis2(formula = as.formula(paste0("counts_data~", "condition")), 
                     data = metadata_tmp, method="euclidean", # method="bray", #otu_data~TIME
                     permutations = 999, sqrt.dist = FALSE, add = FALSE, by = "terms")
pv = permanova$`Pr(>F)`[1]
# print(pv)

rm(counts_data, metadata_tmp)
pca_tmp <- rbind(res_pca$ind$coord,
                 res_pca$ind.sup$coord) %>% data.frame() %>% 
  rownames_to_column("sample")


pca_data <- left_join(pca_tmp, rownames_to_column(metadata_table), by=join_by("sample" == "rowname"))
rm(pca_tmp)

D1_text = paste0("Dim 1 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[1], digits=2), 
                 "%)")
D2_text = paste0("Dim 2 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[2], digits=2), 
                 "%)")
D3_text = paste0("Dim 3 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[3], digits=2), 
                 "%)")

ggplot(pca_data) +
  geom_point(aes(x=Dim.1, y=Dim.2, colour=color, ), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.2, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D2_text) +
  ggtitle("PCA metatranscriptomics") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p1
 

ggplot(pca_data) +
  geom_point(aes(x=Dim.1, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D3_text) +
  ggtitle("PCA metatranscriptomics") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p2

ggplot(pca_data) +
  geom_point(aes(x=Dim.2, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.2, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D2_text) + 
  ylab(D3_text) +
  ggtitle("PCA metatranscriptomics") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p3

plotgrid_PCA <- ggarrange(p1, p2, p3, labels = c("A", "B", "C"), common.legend=TRUE, legend="bottom", nrow=1) 

print(plotgrid_PCA)

ggsave(plot = plotgrid_PCA, filename = "../figures/PCA_metatranscriptomics_3_composantes.tiff", dpi = 300, width = 15, height = 5, bg="white")

ggsave(plot=p1, filename = "../figures/PCA_metatranscriptomics.tiff", dpi = 300, width = 6, height = 5, bg="white")
row_coord <- res_pca$ind$coord

invisible(rgl::open3d())

#rgl::bg3d("lightgray")
rgl::plot3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1], 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2], 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3],
            xlab = paste0(colnames(row_coord)[1] , " (" , substr(as.character(res_pca$eig[,2][1]), 1, 5) , "%)"),
            ylab = paste0(colnames(row_coord)[2] , " (" , substr(as.character(res_pca$eig[,2][2]), 1, 5) , "%)"),
            zlab = paste0(colnames(row_coord)[3] , " (" , substr(as.character(res_pca$eig[,2][3]), 1, 5) , "%)"),
            xlim = c(min(row_coord[, 1]-10), max(row_coord[, 1])+10), 
            ylim = c(min(row_coord[, 2]-10), max(row_coord[, 2])+10), 
            zlim = c(min(row_coord[, 3]-10), max(row_coord[, 3])+10),
            col = "darkcyan",
            size=10,
            main = "PCA community")

rgl::text3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1]+5, 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2]+5, 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3]+5,
            text=c("WN_TF_1", "WN_TF_2", "WN_TF_3"),
            col = "darkcyan",
            size=10)


rgl::points3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1], 
              y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2], 
              z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3],
              col = "darkorange",
              size=10)

rgl::text3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1]+5, 
            y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2]+5, 
            z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3]+5,
            text=c("SD_TF_1", "SD_TF_2", "SD_TF_3"),
            col = "darkorange",
            size=10)

# Activate for or gif generation
par3d(windowRect = c(20, 30, 800, 800))

# rgl::movie3d(
#  movie="3dAnimated_PCA_metaT_community",
#  spin3d( axis = c(0, 0, 1), rpm = 3),
#  duration = 20,
#  dir = "../figures",
#  type = "gif",
#  clean = TRUE, webshot=FALSE, fps=20)

PCA metabolomics

par(mfrow = c(2,2))
res_pca_metaB_all_times <- PCA(t(metabolomics_all_times_clr), scale.unit = TRUE, graph = FALSE)
metabolomics_data <- t(metabolomics_all_times_clr)
metabolomics_tmp <- data.frame(metadata_table_metaB_all_times, stringsAsFactors = TRUE)
permanova <- adonis2(formula = as.formula(paste0("metabolomics_data~", "condition")),
                     data = metabolomics_tmp, method="euclidean", 
                     permutations = 999, sqrt.dist = FALSE, add = FALSE, by = "terms")
pv = permanova$`Pr(>F)`[1]
# print(pv)

rm(metabolomics_data, metabolomics_tmp)
pca_tmp_metaB <- rbind(res_pca_metaB_all_times$ind$coord,
                 res_pca_metaB_all_times$ind.sup$coord) %>% data.frame() %>% 
  rownames_to_column("sample")


pca_data_metaB <- left_join(pca_tmp_metaB, rownames_to_column(metadata_table_metaB_all_times), by=join_by("sample" == "rowname"))
rm(pca_tmp_metaB)

D1_text = paste0("Dim 1 (", 
                 round(data.frame(res_pca_metaB_all_times$eig)$percentage.of.variance[1], digits=2), 
                 "%)")
D2_text = paste0("Dim 2 (", 
                 round(data.frame(res_pca_metaB_all_times$eig)$percentage.of.variance[2], digits=2), 
                 "%)")
D3_text = paste0("Dim 3 (", 
                 round(data.frame(res_pca_metaB_all_times$eig)$percentage.of.variance[3], digits=2), 
                 "%)")

ggplot(pca_data_metaB) +
  geom_point(aes(x=Dim.1, y=Dim.2, colour=color, ), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.2, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D2_text) +
  ggtitle("PCA meta-mebolomics") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p1_metaB
 

ggplot(pca_data_metaB) +
  geom_point(aes(x=Dim.1, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D3_text) +
  ggtitle("PCA meta-mebolomics") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p2_metaB

ggplot(pca_data_metaB) +
  geom_point(aes(x=Dim.2, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.2, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D2_text) + 
  ylab(D3_text) +
  ggtitle("PCA meta-mebolomics") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p3_metaB

plotgrid_PCA_metaB <- ggarrange(p1_metaB, p2_metaB, p3_metaB, labels = c("A", "B", "C"), common.legend=TRUE, legend="bottom", nrow=1) 

print(plotgrid_PCA_metaB)

ggsave(plot = p1_metaB, filename = "../figures/PCA_metabolomics_all_times.tiff", dpi = 300, width = 5, height = 5, bg="white")

ggsave(plot = plotgrid_PCA_metaB, filename = "../figures/PCA_metabolomics_3_composantes_all_times.tiff", dpi = 300, width = 15, height = 5, bg="white")

ggsave(plot=p1_metaB, filename = "../figures/PCA_metabolomics_all_times.tiff", dpi = 300, width = 6, height = 5, bg="white")
row_coord <- res_pca_metaB_all_times$ind$coord

invisible(rgl::open3d())

#rgl::bg3d("lightgray")
rgl::plot3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1], 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2], 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3],
            xlab = paste0(colnames(row_coord)[1] , " (" , substr(as.character(res_pca$eig[,2][1]), 1, 5) , "%)"),
            ylab = paste0(colnames(row_coord)[2] , " (" , substr(as.character(res_pca$eig[,2][2]), 1, 5) , "%)"),
            zlab = paste0(colnames(row_coord)[3] , " (" , substr(as.character(res_pca$eig[,2][3]), 1, 5) , "%)"),
            xlim = c(min(row_coord[, 1]-10), max(row_coord[, 1])+10), 
            ylim = c(min(row_coord[, 2]-10), max(row_coord[, 2])+10), 
            zlim = c(min(row_coord[, 3]-10), max(row_coord[, 3])+10),
            col = "darkcyan",
            size=10,
            main = "PCA meta-metabolomics community")

rgl::text3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1]+5, 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2]+5, 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3]+5,
            text=c("WN_TF_1", "WN_TF_2", "WN_TF_3"),
            col = "darkcyan",
            size=10)


rgl::points3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1], 
              y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2], 
              z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3],
              col = "darkorange",
              size=10)

rgl::text3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1]+5, 
            y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2]+5, 
            z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3]+5,
            text=c("SD_TF_1", "SD_TF_2", "SD_TF_3"),
            col = "darkorange",
            size=10)


rgl::points3d(x=row_coord[c("WN_T0_1", "WN_T0_2", "WN_T0_3"), 1], 
              y=row_coord[c("WN_T0_1", "WN_T0_2", "WN_T0_3"), 2], 
              z=row_coord[c("WN_T0_1", "WN_T0_2", "WN_T0_3"), 3],
              col = "darkcyan",
              size=10)

rgl::text3d(x=row_coord[c("WN_T0_1", "WN_T0_2", "WN_T0_3"), 1]+5, 
            y=row_coord[c("WN_T0_1", "WN_T0_2", "WN_T0_3"), 2]+5, 
            z=row_coord[c("WN_T0_1", "WN_T0_2", "WN_T0_3"), 3]+5,
            text=c("WN_T0_1", "WN_T0_2", "WN_T0_3"),
            col = "darkcyan",
            size=10)


rgl::points3d(x=row_coord[c("SD_T0_1", "SD_T0_2", "SD_T0_3"), 1], 
              y=row_coord[c("SD_T0_1", "SD_T0_2", "SD_T0_3"), 2], 
              z=row_coord[c("SD_T0_1", "SD_T0_2", "SD_T0_3"), 3],
              col = "darkorange",
              size=10)

rgl::text3d(x=row_coord[c("SD_T0_1", "SD_T0_2", "SD_T0_3"), 1]+5, 
            y=row_coord[c("SD_T0_1", "SD_T0_2", "SD_T0_3"), 2]+5, 
            z=row_coord[c("SD_T0_1", "SD_T0_2", "SD_T0_3"), 3]+5,
            text=c("SD_T0_1", "SD_T0_2", "SD_T0_3"),
            col = "darkorange",
            size=10)



# Activate for or gif generation
# par3d(windowRect = c(20, 30, 800, 800))
# 
# rgl::movie3d(
#  movie="3dAnimated_PCA_metaB_community",
#  spin3d( axis = c(0, 0, 1), rpm = 3),
#  duration = 20,
#  dir = "../figures",
#  type = "gif",
#  clean = TRUE, webshot=FALSE, fps=20)

Individual exploratory analysis of metatranscriptomics data by species

Data preparation

Load data by species

diohu_geneid <- annotation_table$Organism == "D.hungarica"
diohu_df <- counts_standard[startsWith(rownames_to_column(counts_standard)$rowname, "D.hungarica"),]

psesy_geneid <- annotation_table$Organism == "P.syringae"
psesy_df <- counts_standard[startsWith(rownames_to_column(counts_standard)$rowname, "P.syringae"),]

psegr_geneid <- annotation_table$Organism == "P.graminis"
psegr_df <- counts_standard[startsWith(rownames_to_column(counts_standard)$rowname, "P.graminis"),]

rhoen_geneid <- annotation_table$Organism == "R.enclensis"
rhoen_df <- counts_standard[startsWith(rownames_to_column(counts_standard)$rowname, "R.enclensis"),]

Zeroes smoothing by species

## remaining zeroes smoothing (as in Zhang et al. 2021)
min_val <- apply(diohu_df, 1, function(x) (min(x[x>0])/2))
for (gene in row.names(diohu_df)) {
  diohu_df[gene,][diohu_df[gene,] == 0] <- min_val[gene]
}

min_val <- apply(psesy_df, 1, function(x) (min(x[x>0])/2))
for (gene in row.names(psesy_df)) {
  psesy_df[gene,][psesy_df[gene,] == 0] <- min_val[gene]
}

min_val <- apply(psegr_df, 1, function(x) (min(x[x>0])/2))
for (gene in row.names(psegr_df)) {
  psegr_df[gene,][psegr_df[gene,] == 0] <- min_val[gene]
}

min_val <- apply(rhoen_df, 1, function(x) (min(x[x>0])/2))
for (gene in row.names(rhoen_df)) {
  rhoen_df[gene,][rhoen_df[gene,] == 0] <- min_val[gene]
}

CLR Transformation of counts by species

diohu_clr <- diohu_df
psesy_clr <- psesy_df
psegr_clr <- psegr_df
rhoen_clr <- rhoen_df

for (samp in samples) {
    diohu_clr[,samp] <- as.vector(clr(diohu_df[,samp]))
    psesy_clr[,samp] <- as.vector(clr(psesy_df[,samp]))
    psegr_clr[,samp] <- as.vector(clr(psegr_df[,samp]))
    rhoen_clr[,samp] <- as.vector(clr(rhoen_df[,samp]))
}

Transcriptomics counts histograms by species

Dioszegia hungarica

par(mfrow=c(1,1))
hist(unlist(diohu_clr),
     breaks = 200,
     cex.axis = 0.7,
     las = 1,
     col = "skyblue",
     ylim = c(0,1800),
     xlim = c(-5,15),
     xlab = "clr-transformed counts",
     main = "Distribution of D. hungarica clr-transformed counts")

Pseudomonas graminis

par(mfrow=c(1,1))
hist(unlist(psegr_clr),
     breaks = 200,
     cex.axis = 0.7,
     las = 1,
     col = "skyblue",
     ylim = c(0,1800),
     xlim = c(-5,15),
     xlab = "clr-transformed counts",
     main = "Distribution of P. graminis clr-transformed counts")

Very few P. graminis counts, probably not exploitable.

Pseudomonas syringae

par(mfrow=c(1,1))
hist(unlist(psesy_clr),
     breaks = 200,
     cex.axis = 0.7,
     las = 1,
     col = "skyblue",
     ylim = c(0,1800),
     xlim = c(-5,15),
     xlab = "clr-transformed counts",
     main = "Distribution of P. syringae clr-transformed counts")

Rhodococcus enclensis

par(mfrow=c(1,1))
hist(unlist(rhoen_clr),
     breaks = 200,
     cex.axis = 0.7,
     las = 1,
     col = "skyblue",
     ylim = c(0,1800),
     xlim = c(-5,15),
     xlab = "clr-transformed counts",
     main = "Distribution of R. enclensis clr-transformed counts")

Transcriptomics counts box-plots by species

Dioszegia hungarica

boxplot(diohu_clr,
        main = "D. hungarica clr-transformed expression",
        horizontal = TRUE,
        col = metadata_table$color,
        cex = 0.5,
        cex.axis = 0.8,
        las = 1)

Pseudomonas graminis

boxplot(psegr_clr,
        main = "P. graminis clr-transformed expression",
        horizontal = TRUE,
        col = metadata_table$color,
        cex = 0.5,
        cex.axis = 0.8,
        las = 1)

Pseudomonas syringae

boxplot(psesy_clr,
        main = "P. syringae clr-transformed expression",
        horizontal = TRUE,
        col = metadata_table$color,
        cex = 0.5,
        cex.axis = 0.8,
        las = 1)

Rhodococcus enclensis

boxplot(rhoen_clr,
        main = "R. enclensis clr-transformed expression",
        horizontal = TRUE,
        col = metadata_table$color,
        cex = 0.5,
        cex.axis = 0.8,
        las = 1)

Transcriptomics counts PCA by species

Dioszegia hungarica

res_pca <- PCA(t(diohu_clr), scale.unit = TRUE, graph = FALSE)

#fviz_pca_ind(res_pca,
#             col.ind = metadata_table$color,
#             mean.point = FALSE,
#             title = "PCA on D. hungarica clr-transformed counts")
counts_data <- t(diohu_clr)
metadata_tmp <- data.frame(metadata_table, stringsAsFactors = TRUE)
permanova <- adonis2(formula = as.formula(paste0("counts_data~", "condition")), 
                     data = metadata_tmp, method="euclidean", # method="bray", #otu_data~TIME
                     permutations = 999, sqrt.dist = FALSE, add = FALSE, by = "terms")
pv = permanova$`Pr(>F)`[1]
# print(pv)

rm(counts_data, metadata_tmp)
pca_tmp <- rbind(res_pca$ind$coord,
                 res_pca$ind.sup$coord) %>% data.frame() %>% 
  rownames_to_column("sample")


pca_data <- left_join(pca_tmp, rownames_to_column(metadata_table), by=join_by("sample" == "rowname"))
rm(pca_tmp)

D1_text = paste0("Dim 1 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[1], digits=2), 
                 "%)")
D2_text = paste0("Dim 2 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[2], digits=2), 
                 "%)")
D3_text = paste0("Dim 3 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[3], digits=2), 
                 "%)")

ggplot(pca_data) +
  geom_point(aes(x=Dim.1, y=Dim.2, colour=color, ), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.2, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D2_text) +
  ggtitle("PCA metatranscriptomics  \nD. hungarica") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p1
 

ggplot(pca_data) +
  geom_point(aes(x=Dim.1, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D3_text) +
  ggtitle("PCA metatranscriptomics  \nD. hungarica") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p2

ggplot(pca_data) +
  geom_point(aes(x=Dim.2, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.2, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D2_text) + 
  ylab(D3_text) +
  ggtitle("PCA metatranscriptomics  \nD. hungarica") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p3

plotgrid_PCA <- ggarrange(p1, p2, p3, labels = c("A", "B", "C"), common.legend=TRUE, legend="bottom", nrow=1) 

print(plotgrid_PCA)

ggsave(plot = plotgrid_PCA, filename = "../figures/PCA_metatranscriptomics_3_composantes_diohu.tiff", dpi = 300, width = 15, height = 5, bg="white")

ggsave(plot=p1, filename = "../figures/PCA_metatranscriptomics_diohu.tiff", dpi = 300, width = 6, height = 5, bg="white")
row_coord <- res_pca$ind$coord


invisible(rgl::open3d())

#rgl::bg3d("lightgray")
rgl::plot3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1], 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2], 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3],
            xlab = paste0(colnames(row_coord)[1] , " (" , substr(as.character(res_pca$eig[,2][1]), 1, 5) , "%)"),
            ylab = paste0(colnames(row_coord)[2] , " (" , substr(as.character(res_pca$eig[,2][2]), 1, 5) , "%)"),
            zlab = paste0(colnames(row_coord)[3] , " (" , substr(as.character(res_pca$eig[,2][3]), 1, 5) , "%)"),
            xlim = c(min(row_coord[, 1]), max(row_coord[, 1])+10), 
            ylim = c(min(row_coord[, 2]), max(row_coord[, 2])+10), 
            zlim = c(min(row_coord[, 3]), max(row_coord[, 3])+10),
            col = "darkcyan",
            size=10,
            main = "PCA D. hungarica")

rgl::text3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1]+5, 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2]+5, 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3]+5,
            text=c("WN_TF_1", "WN_TF_2", "WN_TF_3"),
            col = "darkcyan",
            size=10)


rgl::points3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1], 
              y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2], 
              z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3],
              col = "darkorange",
              size=10)

rgl::text3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1]+5, 
            y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2]+5, 
            z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3]+5,
            text=c("SD_TF_1", "SD_TF_2", "SD_TF_3"),
            col = "darkorange",
            size=10)

## Activate for or gif generation
#par3d(windowRect = c(20, 30, 800, 800))

#rgl::movie3d(
#  movie="3DAnimated_PCA_diohu", 
#  spin3d( axis = c(0, 0, 1), rpm = 3),
#  duration = 20, 
#  dir = "../figures",
#  type = "gif", 
#  clean = TRUE, webshot=FALSE, fps=10)

Pseudomonas graminis

res_pca <- PCA(t(psegr_clr), scale.unit = TRUE, graph = FALSE)
counts_data <- t(psegr_clr)
metadata_tmp <- data.frame(metadata_table, stringsAsFactors = TRUE)
permanova <- adonis2(formula = as.formula(paste0("counts_data~", "condition")), 
                     data = metadata_tmp, method="euclidean", # method="bray", #otu_data~TIME
                     permutations = 999, sqrt.dist = FALSE, add = FALSE, by = "terms")
pv = permanova$`Pr(>F)`[1]
# print(pv)

rm(counts_data, metadata_tmp)
pca_tmp <- rbind(res_pca$ind$coord,
                 res_pca$ind.sup$coord) %>% data.frame() %>% 
  rownames_to_column("sample")


pca_data <- left_join(pca_tmp, rownames_to_column(metadata_table), by=join_by("sample" == "rowname"))
rm(pca_tmp)

D1_text = paste0("Dim 1 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[1], digits=2), 
                 "%)")
D2_text = paste0("Dim 2 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[2], digits=2), 
                 "%)")
D3_text = paste0("Dim 3 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[3], digits=2), 
                 "%)")

ggplot(pca_data) +
  geom_point(aes(x=Dim.1, y=Dim.2, colour=color, ), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.2, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D2_text) +
  ggtitle("PCA metatranscriptomics  \nP. graminis") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p1
 

ggplot(pca_data) +
  geom_point(aes(x=Dim.1, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D3_text) +
  ggtitle("PCA metatranscriptomics  \nP. graminis") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p2

ggplot(pca_data) +
  geom_point(aes(x=Dim.2, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.2, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D2_text) + 
  ylab(D3_text) +
  ggtitle("PCA metatranscriptomics  \nP. graminis") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p3

plotgrid_PCA <- ggarrange(p1, p2, p3, labels = c("A", "B", "C"), common.legend=TRUE, legend="bottom", nrow=1) 

print(plotgrid_PCA)

ggsave(plot = plotgrid_PCA, filename = "../figures/PCA_metatranscriptomics_3_composantes_psegr.tiff", dpi = 300, width = 15, height = 5, bg="white")

ggsave(plot=p1, filename = "../figures/PCA_metatranscriptomics_psegr.tiff", dpi = 300, width = 6, height = 5, bg="white")
row_coord <- res_pca$ind$coord

invisible(rgl::open3d())

#rgl::bg3d("lightgray")
rgl::plot3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1], 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2], 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3],
            xlab = paste0(colnames(row_coord)[1] , " (" , substr(as.character(res_pca$eig[,2][1]), 1, 5) , "%)"),
            ylab = paste0(colnames(row_coord)[2] , " (" , substr(as.character(res_pca$eig[,2][2]), 1, 5) , "%)"),
            zlab = paste0(colnames(row_coord)[3] , " (" , substr(as.character(res_pca$eig[,2][3]), 1, 5) , "%)"),
            xlim = c(min(row_coord[, 1]), max(row_coord[, 1])+10), 
            ylim = c(min(row_coord[, 2]), max(row_coord[, 2])+10), 
            zlim = c(min(row_coord[, 3]), max(row_coord[, 3])+10),
            col = "darkcyan",
            size=10,
            main = "PCA P. graminis")

rgl::text3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1]+5, 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2]+5, 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3]+5,
            text=c("WN_TF_1", "WN_TF_2", "WN_TF_3"),
            col = "darkcyan",
            size=10)


rgl::points3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1], 
              y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2], 
              z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3],
              col = "darkorange",
              size=10)

rgl::text3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1]+3, 
            y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2]+3, 
            z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3]+3,
            text=c("SD_TF_1", "SD_TF_2", "SD_TF_3"),
            col = "darkorange",
            size=10)

## Activate for or gif generation
#par3d(windowRect = c(20, 30, 800, 800))

#rgl::movie3d(
#  movie="3DAnimated_PCA_psegr", 
#  spin3d( axis = c(0, 0, 1), rpm = 3),
#  duration = 20, 
#  dir = "../figures",
#  type = "gif", 
#  clean = TRUE, webshot=FALSE, fps=10)

Pseudomonas syringae

res_pca <- PCA(t(psesy_clr), scale.unit = TRUE, graph = FALSE)
counts_data <- t(psesy_clr)
metadata_tmp <- data.frame(metadata_table, stringsAsFactors = TRUE)
permanova <- adonis2(formula = as.formula(paste0("counts_data~", "condition")), 
                     data = metadata_tmp, method="euclidean", # method="bray", #otu_data~TIME
                     permutations = 999, sqrt.dist = FALSE, add = FALSE, by = "terms")
pv = permanova$`Pr(>F)`[1]
# print(pv)

rm(counts_data, metadata_tmp)
pca_tmp <- rbind(res_pca$ind$coord,
                 res_pca$ind.sup$coord) %>% data.frame() %>% 
  rownames_to_column("sample")


pca_data <- left_join(pca_tmp, rownames_to_column(metadata_table), by=join_by("sample" == "rowname"))
rm(pca_tmp)

D1_text = paste0("Dim 1 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[1], digits=2), 
                 "%)")
D2_text = paste0("Dim 2 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[2], digits=2), 
                 "%)")
D3_text = paste0("Dim 3 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[3], digits=2), 
                 "%)")

ggplot(pca_data) +
  geom_point(aes(x=Dim.1, y=Dim.2, colour=color, ), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.2, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D2_text) +
  ggtitle("PCA metatranscriptomics  \nP. syringae") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p1
 

ggplot(pca_data) +
  geom_point(aes(x=Dim.1, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D3_text) +
  ggtitle("PCA metatranscriptomics  \nP. syringae") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p2

ggplot(pca_data) +
  geom_point(aes(x=Dim.2, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.2, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D2_text) + 
  ylab(D3_text) +
  ggtitle("PCA metatranscriptomics  \nP. syringae") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p3

plotgrid_PCA <- ggarrange(p1, p2, p3, labels = c("A", "B", "C"), common.legend=TRUE, legend="bottom", nrow=1) 

print(plotgrid_PCA)

ggsave(plot = plotgrid_PCA, filename = "../figures/PCA_metatranscriptomics_3_composantes_psesy.tiff", dpi = 300, width = 15, height = 5, bg="white")

ggsave(plot=p1, filename = "../figures/PCA_metatranscriptomics_psesy.tiff", dpi = 300, width = 6, height = 5, bg="white")
row_coord <- res_pca$ind$coord

invisible(rgl::open3d())

#rgl::bg3d("lightgray")
rgl::plot3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1], 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2], 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3],
            xlab = paste0(colnames(row_coord)[1] , " (" , substr(as.character(res_pca$eig[,2][1]), 1, 5) , "%)"),
            ylab = paste0(colnames(row_coord)[2] , " (" , substr(as.character(res_pca$eig[,2][2]), 1, 5) , "%)"),
            zlab = paste0(colnames(row_coord)[3] , " (" , substr(as.character(res_pca$eig[,2][3]), 1, 5) , "%)"),
            xlim = c(min(row_coord[, 1]), max(row_coord[, 1])+10), 
            ylim = c(min(row_coord[, 2]), max(row_coord[, 2])+10), 
            zlim = c(min(row_coord[, 3]), max(row_coord[, 3])+10),
            col = "darkcyan",
            size=10,
            main = "PCA P. syringae")

rgl::text3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1]+3, 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2]+3, 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3]+3,
            text=c("WN_TF_1", "WN_TF_2", "WN_TF_3"),
            col = "darkcyan",
            size=10)


rgl::points3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1], 
              y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2], 
              z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3],
              col = "darkorange",
              size=10)

rgl::text3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1]+3, 
            y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2]+3, 
            z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3]+3,
            text=c("SD_TF_1", "SD_TF_2", "SD_TF_3"),
            col = "darkorange",
            size=10)


## Activate for or gif generation
#par3d(windowRect = c(20, 30, 800, 800))

#rgl::movie3d(
#  movie="3DAnimated_PCA_psesy", 
#  spin3d( axis = c(0, 0, 1), rpm = 3),
#  duration = 20, 
#  dir = "../figures",
#  type = "gif", 
#  clean = TRUE, webshot=FALSE, fps=10)

Rhodococcus enclensis

res_pca <- PCA(t(rhoen_clr), scale.unit = TRUE, graph = FALSE)
counts_data <- t(rhoen_clr)
metadata_tmp <- data.frame(metadata_table, stringsAsFactors = TRUE)
permanova <- adonis2(formula = as.formula(paste0("counts_data~", "condition")), 
                     data = metadata_tmp, method="euclidean", # method="bray", #otu_data~TIME
                     permutations = 999, sqrt.dist = FALSE, add = FALSE, by = "terms")
pv = permanova$`Pr(>F)`[1]
# print(pv)

rm(counts_data, metadata_tmp)
pca_tmp <- rbind(res_pca$ind$coord,
                 res_pca$ind.sup$coord) %>% data.frame() %>% 
  rownames_to_column("sample")


pca_data <- left_join(pca_tmp, rownames_to_column(metadata_table), by=join_by("sample" == "rowname"))
rm(pca_tmp)

D1_text = paste0("Dim 1 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[1], digits=2), 
                 "%)")
D2_text = paste0("Dim 2 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[2], digits=2), 
                 "%)")
D3_text = paste0("Dim 3 (", 
                 round(data.frame(res_pca$eig)$percentage.of.variance[3], digits=2), 
                 "%)")

ggplot(pca_data) +
  geom_point(aes(x=Dim.1, y=Dim.2, colour=color, ), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.2, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D2_text) +
  ggtitle("PCA metatranscriptomics  \nR. enclensis") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p1
 

ggplot(pca_data) +
  geom_point(aes(x=Dim.1, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.1, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D1_text) + 
  ylab(D3_text) +
  ggtitle("PCA metatranscriptomics  \nR. enclensis") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p2

ggplot(pca_data) +
  geom_point(aes(x=Dim.2, y=Dim.3, colour=color), size=3) +
  scale_colour_identity("condition", labels=c("WN", "SD"), guide = "legend") +
  ggrepel::geom_text_repel(aes(x=Dim.2, y=Dim.3, colour=color, label=sample), 
                           nudge_y = -2,  seed = 42, segment.size=0.1, show.legend = FALSE) +
  xlab(D2_text) + 
  ylab(D3_text) +
  ggtitle("PCA metatranscriptomics  \nR. enclensis") +
  labs(caption =  paste0("PERMANOVA on condition: p-value: ", pv)) + 
  theme(panel.background= element_rect(fill="#f4f4f4"),
        plot.caption = element_text(size=7)) -> p3

plotgrid_PCA <- ggarrange(p1, p2, p3, labels = c("A", "B", "C"), common.legend=TRUE, legend="bottom", nrow=1) 

print(plotgrid_PCA)

ggsave(plot = plotgrid_PCA, filename = "../figures/PCA_metatranscriptomics_3_composantes_rhoen.tiff", dpi = 300, width = 15, height = 5, bg="white")

ggsave(plot=p1, filename = "../figures/PCA_metatranscriptomics_rhoen.tiff", dpi = 300, width = 6, height = 5, bg="white")
row_coord <- res_pca$ind$coord

invisible(rgl::open3d())

#rgl::bg3d("lightgray")
rgl::plot3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1], 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2], 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3],
            xlab = paste0(colnames(row_coord)[1] , " (" , substr(as.character(res_pca$eig[,2][1]), 1, 5) , "%)"),
            ylab = paste0(colnames(row_coord)[2] , " (" , substr(as.character(res_pca$eig[,2][2]), 1, 5) , "%)"),
            zlab = paste0(colnames(row_coord)[3] , " (" , substr(as.character(res_pca$eig[,2][3]), 1, 5) , "%)"),
            xlim = c(min(row_coord[, 1]), max(row_coord[, 1])+10), 
            ylim = c(min(row_coord[, 2]), max(row_coord[, 2])+10), 
            zlim = c(min(row_coord[, 3]), max(row_coord[, 3])+10),
            col = "darkcyan",
            size=10,
            main = "PCA R. enclensis")

rgl::text3d(x=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 1]+3, 
            y=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 2]+3, 
            z=row_coord[c("WN_TF_1", "WN_TF_2", "WN_TF_3"), 3]+3,
            text=c("WN_TF_1", "WN_TF_2", "WN_TF_3"),
            col = "darkcyan",
            size=10)


rgl::points3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1], 
              y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2], 
              z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3],
              col = "darkorange",
              size=10)

rgl::text3d(x=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 1]+3, 
            y=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 2]+3, 
            z=row_coord[c("SD_TF_1", "SD_TF_2", "SD_TF_3"), 3]+3,
            text=c("SD_TF_1", "SD_TF_2", "SD_TF_3"),
            col = "darkorange",
            size=10)


## Activate for or gif generation
#par3d(windowRect = c(20, 30, 800, 800))

#rgl::movie3d(
#  movie="3DAnimated_PCA_rhoen", 
#  spin3d( axis = c(0, 0, 1), rpm = 3),
#  duration = 20, 
#  dir = "../figures",
#  type = "gif", 
#  clean = TRUE, webshot=FALSE, fps=10)

Samples hierarchical clustering by species

Dioszegia hungarica

#### Sample distances ####
message("Computing inter-sample distances")

## Pearson
dist_pearson_diohu <- as.dist(1 - cor(diohu_clr, use = "everything", 
                                method = "pearson"))
message("Sample clustering")

tree_pearson_diohu <- hclust(dist_pearson_diohu, method = "complete")
par(bg = "white", mfrow=c(1, 1))
plotColoredClusters(tree_pearson_diohu, labs = row.names(metadata_table),
                    ylab = NA, xlab = NA, cex = 1, las = 1,
                    cols = metadata_table$color, col = "black",
                    main = "Samples Pearson distance hierarchical clustering,
complete linkage, D. hungarica genes.")

Natural separation of samples according to their incubation condition for D. hungarica.

Pseudomonas graminis

#### Sample distances ####
message("Computing inter-sample distances")

## Pearson
dist_pearson_psegr <- as.dist(1 - cor(psegr_clr, use = "everything", 
                                method = "pearson"))
message("Sample clustering")

tree_pearson_psegr <- hclust(dist_pearson_psegr, method = "complete")
par(bg = "white", mfrow=c(1, 1))
plotColoredClusters(tree_pearson_psegr, labs = row.names(metadata_table),
                    ylab = NA, xlab = NA, cex = 1, las = 1,
                    cols = metadata_table$color, col = "black",
                    main = "Samples Pearson distance hierarchical clustering,
complete linkage, P. graminis genes.")

For P. graminis, the clustering does not distinguish between the two incubation conditions, probably because of the very low amounts of counts attributed to this species.

Pseudomonas syringae

#### Sample distances ####
message("Computing inter-sample distances")

## Pearson
dist_pearson_psesy <- as.dist(1 - cor(psesy_clr, use = "everything", 
                                method = "pearson"))
message("Sample clustering")

tree_pearson_psesy <- hclust(dist_pearson_psesy, method = "complete")
par(bg = "white", mfrow=c(1, 1))
plotColoredClusters(tree_pearson_psesy, labs = row.names(metadata_table),
                    ylab = NA, xlab = NA, cex = 1, las = 1,
                    cols = metadata_table$color, col = "black",
                    main = "Samples Pearson distance hierarchical clustering,
complete linkage, P. syringae genes.")

Samples are separated according to their experimental condition, which is encouraging for further analysis of P. syringae.

Rhodococcus enclensis

#### Sample distances ####
message("Computing inter-sample distances")

## Pearson
dist_pearson_rhoen <- as.dist(1 - cor(rhoen_clr, use = "everything", 
                                method = "pearson"))
message("Sample clustering")

tree_pearson_rhoen <- hclust(dist_pearson_rhoen, method = "complete")
par(bg = "white", mfrow=c(1, 1))
plotColoredClusters(tree_pearson_rhoen, labs = row.names(metadata_table),
                    ylab = NA, xlab = NA, cex = 1, las = 1,
                    cols = metadata_table$color, col = "black",
                    main = "Samples Pearson distance hierarchical clustering,
complete linkage, R. enclensis genes.")

Again, samples are naturally separated according to their incubation condition for R. enclensis.

Differential analyses with MTXmodel (whole community metatranscriptomics data)

MTXmodel was used on the complete community at once. As input, filtered data (without the undetected genes) but untransformed was given to MTXmodel, as it performs its own CLR normalisation.

analysis_method = 'LM'

correction = 'BH',

fit_data <- MTXmodel(
    counts_standard, metadata_table, 'MTXmodel_output',
    cores = 2,
    fixed_effects = c('temperature'),
    reference = c("temperature,5"),
    min_abundance = 0,
    min_prevalence = 0,
    normalization = 'CLR',
    analysis_method = 'LM',
    correction = 'BH',
    standardize = FALSE,
    transform = 'NONE',
    plot_scatter = FALSE,
    plot_heatmap = TRUE)
# par(mar=c(5,5,5,5), cex=1.0, cex.main=1.4, cex.axis=1.4, cex.lab=1.4)
# topT <- read.csv("MTXmodel_output/all_results.tsv", sep="\t", row.names="feature")
# 
# #topT <- as.data.frame(resDESeq)
# 
# #Adjusted P values (FDR Q values)
# with(topT, plot(coef, -log10(qval), pch=20, main="Volcano plot community", col="white", xlab=bquote(~MTXmodel~coefficient), ylab=bquote(~-log[10]~q~value), xlim=c(0.4,-0.4), ylim=c(0.6,1.2)))
# 
# with(subset(topT, qval<=0.2 & coef<=-0.1), points(coef, -log10(qval), pch=21, col="blue", bg="lightblue", cex=1.4, lwd=2))
# with(subset(topT, qval<=0.2 & coef>=0.1), points(coef, -log10(qval), pch=21, col="orange", bg="gold", cex=1.4, lwd=2))
# with(subset(topT, qval>0.2 | abs(coef)<0.1), points(coef, -log10(qval), pch=21, col="black", bg="grey", cex=1.4, lwd=2))
# 
# 
# 
# #Add lines for absolute FC>1 and P-value cut-off at FDR p adjusted value<0.2
# abline(v=0, col="black", lty=3, lwd=1.0)
# abline(v=-0.1, col="black", lty=4, lwd=1.0)
# abline(v=0.1, col="black", lty=4, lwd=1.0)
# abline(h=-log10(0.2), col="black", lty=4, lwd=1.0)
# #abline(h=-log10(max(topT$pvalue[topT$padj<0.2], na.rm=TRUE)), col="black", lty=4, lwd=2.0)
# Loading MTXmodel results
res_mtx <- read.csv("../scripts/MTXmodel_output/all_results.tsv", sep="\t", row.names="feature")


tryCatch({
  inner_join(rownames_to_column(res_mtx), annotation_table_fig, by=c("rowname" = "gene")) -> res_mtx_fig
  res_mtx_fig %>% filter(abs(qval) <= 0.2) -> res_mtx_fig
  },
  error=function(e){str(e)
  }
)


## Data for final table
annotation_table_long <- read.csv("../data/annotations_final_community_long.tsv", sep="\t", row.names = "Geneid")

tryCatch({
  annotation_table_long$gene <- row.names(annotation_table_long)
  inner_join(rownames_to_column(res_mtx), annotation_table_long, by=c("rowname" = "gene")) -> res_mtx_filt
  res_mtx_filt %>% filter(abs(qval) <= 0.2) -> res_mtx_filt
  },
  error=function(e){str(e)
  }
)

Differential analyses with DESeq2 (metatranscriptomics data species by species)

As a complementary approach, separate differential analyses were conducted for each species separately with DESeq2.

DESeq2 analyses preparation

metadata_table$temperature <- factor(metadata_table$temperature)

We use filtered counts data (only genes detected in at least 70% of biological samples). Zeroes are conserved as is. We round the counts matrix before performing DESeq2 analysis.

diohu_df <- counts_filtered[diohu_geneid,]
psegr_df <- counts_filtered[psegr_geneid,]
psesy_df <- counts_filtered[psesy_geneid,]
rhoen_df <- counts_filtered[rhoen_geneid,]
res_df <- data.frame(gene=character(), 
                     baseMean=numeric(),
                     log2FoldChange=numeric(), 
                     lfcSE=numeric(), 
                     stat=numeric(), 
                     pvalue=numeric(), 
                     padj=numeric(), 
                     condition=factor(),
                     SAMPLE_COMPARISON=factor(),
                     organism=factor())

Dioszegia hungarica

compute_deseq2_analysis(diohu_df, 
                        metadata_table,
                        #subset_var = "temperature", 
                        #select = "3.5", 
                        contrast_col="temperature", 
                        ref="5", 
                        tested="17") -> res

tryCatch({res$organism <- "D. hungarica"},
  error=function(e){str(e) # prints structure of exception
  })

res_df <- rbind(res_df, res) 

Rhodococcus enclensis

compute_deseq2_analysis(rhoen_df, 
                        metadata_table,
                        #subset_var = "temperature", 
                        #select = "3.5", 
                        contrast_col="temperature", 
                        ref="5", 
                        tested="17") -> res

tryCatch({res$organism <- "R. enclensis"},
  error=function(e){str(e)
  })

res_df <- rbind(res_df, res) 

Pseudomonas syringae

compute_deseq2_analysis(psesy_df, 
                        metadata_table,
                        #subset_var = "temperature", 
                        #select = "3.5", 
                        contrast_col="temperature", 
                        ref="5", 
                        tested="17") -> res

tryCatch({res$organism <- "P. syringae"},
  error=function(e){str(e)
  })

res_df <- rbind(res_df, res) 

Pseudomonas graminis

compute_deseq2_analysis(psegr_df, 
                        metadata_table,
                        #subset_var = "temperature", 
                        #select = "3.5", 
                        contrast_col="temperature", 
                        ref="5", 
                        tested="17") -> res

tryCatch({res$organism <- "P. graminis"},
  error=function(e){str(e)
  })

res_df <- rbind(res_df, res) 

Filter DESeq2 data

tryCatch({
  res_df %>% inner_join(annotation_table_fig, by="gene") -> tmp_res_df
  tmp_res_df %>% filter(padj <= 0.2) -> res_deseq_fig  #& abs(log2FoldChange) >= 1
  },
  error=function(e){str(e)
  }
)

rm(tmp_res_df)

## data for final table
# annotation_table_long <- read.csv("../../mock_communities/data/annotations_final_community.tsv", sep="\t", row.names = "Geneid")
annotation_table_long <- read.csv("../data/annotations_final_community_long.tsv", sep="\t", row.names = "Geneid")

tryCatch({
  annotation_table_long$gene <- row.names(annotation_table_long)
  res_df %>% inner_join(annotation_table_long, by="gene") -> res_df
  res_df %>% filter(padj <= 0.2) -> res_deseq_filt # & abs(log2FoldChange) >= 1
  },
  error=function(e){str(e)
  }
)

Save differentially expressed genes (DEGs) all methods

temp_df <- right_join(rownames_to_column(res_mtx), annotation_table_long, join_by("rowname"=="gene"))
rename(temp_df, "gene" = "rowname") -> temp_df



all_genes <- full_join(res_df, temp_df,  by=c("gene", "locus_tag", "transcriptId", "Organism",
                                              "Chr", "Start", "End", "Strand", "Length",
                                              "product", "COG_process", "COG_category",
                                              "COGid", "GOs", "COG_cat", "COG_category_long",
                                              "ecNum" ),
                       suffix = c("", "w"))

rm(temp_df)
columns_to_remove <- grep(".w", names(all_genes))
all_genes %>% dplyr::select(-columns_to_remove) %>% filter(qval<=0.2 | padj<=0.2 ) -> all_genes_filtered

write.table(all_genes_filtered, "../results/DEG_all_methods_community.tsv", sep='\t', row.names = FALSE)

write.table(res_df, "../results/DEG_DESeq2_all_community.tsv", sep='\t', row.names = FALSE)
sign_deseq2_df <- res_df

Plot DEGs all methods

#### Both methods DEGs


full_join(all_genes_filtered, annotation_table_fig, by="gene") -> data


data$title <- "Differentially expressed genes SD vs WN (DESeq2 & MTXmodel)"
data$Organism <- factor(data$organism, levels=c("D. hungarica", "P. graminis", "P. syringae", "R. enclensis"))




custom_strips <- strip_nested(background_x = elem_list_rect(fill = c("lightgrey", 
                                                                     species_colours[["D.hungarica"]], 
                                                                     species_colours[["P.syringae"]], 
                                                                     species_colours[["R.enclensis"]])),
                              text_x = list(element_text(face = "plain", colour = "black", size = 17),
                                            element_text(face = "italic", colour = "white", size = 15),
                                            element_text(face = "italic", colour = "white", size = 15), 
                                            element_text(face = "italic", colour = "white", size = 15)),
                              by_layer_x = FALSE)


ggplot(data, aes(x = coef, y = COG_category.y,  color = after_scale(alpha(fill, 0.3)), fill=COG_category_long.y, alpha=0.7, label=name_figure)) + 
  geom_point(aes(alpha=0.7), position="dodge") +
  geom_violin(aes(alpha=0.3), show.legend = TRUE) +
  annotate("rect", xmin=-Inf, xmax=0, ymin=-Inf, ymax=Inf, fill="#184ca5", alpha=0.1) +
  annotate("rect", xmin=0, xmax=Inf, ymin=-Inf, ymax=Inf, fill="gold", alpha=0.1) +
  geom_vline(xintercept = 0, linetype="dashed") +
  ylab("COG category") +
  xlab("MTXmodel coefficient") +
  ggrepel::geom_text_repel(nudge_y = 0.5, segment.size=0.1, seed = 42) +
  guides(fill=guide_legend(ncol=3), alpha="none", color="none") + #color="none",
  scale_y_discrete(limits=rev(names(vect_COG_category_long))) +
  scale_colour_manual(limits=vect_COG_category_long, values=COG_colours, drop=FALSE) + 
  scale_fill_manual(limits=vect_COG_category_long, values=COG_colours, drop=FALSE) +
  theme(axis.title = element_text(size=13, "Differentially expressed genes SD vs WN"),
        axis.text = element_text(size=13),
        strip.text.y = element_text(size = 17),
        #strip.text.x = element_text(size = 17, face = "italic"),
        legend.text = element_text(size = 10),
        legend.title = element_blank(),
        legend.key.size = unit(0.5, "line"),
        legend.position = "bottom",
        panel.background = element_rect(fill = "#f4f4f4")) +
  facet_nested(~title + Organism, strip = custom_strips, drop=TRUE) -> plot

print(plot)

ggsave(plot = plot, filename = "../figures/DEG_day_vs_night_commu_both_methods_vertical.tiff", dpi = 300, width = 13, height = 13, bg="white")

Venn diagram of differential expression results

list_venn <- list(res_deseq_filt[(res_deseq_filt$SAMPLE_COMPARISON == "17_VS_5"), "gene"],
                  res_mtx_filt[, "rowname"])

invisible(grid.newpage())   
draw.pairwise.venn(area1 = length(list_venn[[1]]),
                 area2 = length(list_venn[[2]]),
                 cross.area = length(intersect.Vector(list_venn[[1]], list_venn[[2]])),
                 fill = c("#D53F7F", "#039EBD"),
                 lty = "blank",
                 fontfamily = "Helvetica",
                 cex = rep(2, 3),
                 cat.cex = rep(1.5, 2),
                 cat.pos = c(-50, 50),
                 cat.dist = c(-0.05, -0.05),
                 cat.prompts = TRUE,
                 cat.col = c("#D53F7F", "#039EBD"),
                 cat.fontfamily = "Helvetica",
                 category = c("DESeq  \nalone", "MTXModel  \ncommunity"),
                 title = "Differentially abundant genes found by DESeq2 and MTXmodel",
                 margin = 0.1) -> venn_plot

INFO [2025-03-13 17:43:54] Placing category labels at default outer locations.  Use "cat.pos" and "cat.dist" to modify location.
INFO [2025-03-13 17:43:54] Current "cat.pos": -50 degrees, 50 degrees
INFO [2025-03-13 17:43:54] Current "cat.dist": -0.05 , -0.05
# Writing to file

invisible(png(filename = "../figures/Venn_diagram_ALDEXe2_MTX_DESeq_community.png", 
     width = 1000, height = 1000))
invisible(grid.draw(venn_plot))
invisible(dev.off())
vect_degs <- all_genes_filtered$gene
counts_clr_degs <- as.matrix(counts_clr)[vect_degs,]

Differential Metabolites intensity

identified_metabolites <- left_join(metabolomics_annotations[,c("metabolite identification", "ID")],
                                        rownames_to_column(metabolomics_all_times_filtered), by = join_by("ID" == "rowname"))  #rownames_to_column(metabolomics_all_times_clr)

identified_metabolites <- identified_metabolites[identified_metabolites$`metabolite identification` != "unknown",]

row.names(identified_metabolites) <- identified_metabolites$`metabolite identification`

identified_metabolites <- identified_metabolites %>% t() %>% data.frame()


identified_metabolites <- identified_metabolites[3:nrow(identified_metabolites),] 
identified_metabolites$sample <- row.names(identified_metabolites)

identified_metabolites <- left_join(identified_metabolites, rownames_to_column(metadata_table_metaB_all_times), by = join_by("sample" == "rowname"))

identified_metabolites %>% rename("2-Aminobenzoic acid" = "X2.aminobenzoic.acid",
                                      "DL-Methionine sulfoxide" = "DL.methionine.sulfoxide",
                                      "Pyridoxal" = "pyridoxal",
                                      "D-Pantothenic acid" = "D.pantothenic.acid" ,
                                      "N6-Acetyl-L-lysine" = "N6.acetyl.L.lysine",
                                      "L-Glutamic acid" = "L.glutamic.acid",
                                      "L-Isoleucine" = "L.isoleucine",
                                      "Butyryl-L-carnitine" = "butyryl.L.carnitine",
                                      "Acetyl-L-carnitine" = "acetyl.L.carnitine",
                                      "Isovaleryl-L-carnitine" = "isovaleryl.L.carnitine") -> identified_metabolites 

identified_metabolites %>%
  pivot_longer(cols = c("2-Aminobenzoic acid", "DL-Methionine sulfoxide", "Pyridoxal", 
                        "D-Pantothenic acid", "N6-Acetyl-L-lysine", "L-Glutamic acid", 
                        "L-Isoleucine", "Butyryl-L-carnitine", "Acetyl-L-carnitine", 
                        "Isovaleryl-L-carnitine"), 
               values_to = "intensity") -> identified_metabolites
 

  
identified_metabolites[identified_metabolites$temperature == 17 & identified_metabolites$time == 0, "condition"] <- "SD_T0"
identified_metabolites[identified_metabolites$temperature == 5 & identified_metabolites$time == 0, "condition"] <- "WN_T0"
identified_metabolites[identified_metabolites$temperature == 17 & identified_metabolites$time == 3, "condition"] <- "SD_TF"
identified_metabolites[identified_metabolites$temperature == 5 & identified_metabolites$time == 3, "condition"] <- "WN_TF"
identified_metabolites[identified_metabolites$temperature == 17, "fill"] <- "#F8AD18"
identified_metabolites[identified_metabolites$temperature == 5, "fill"] <- "#89DDF8"
identified_metabolites[identified_metabolites$temperature == 17, "colour"] <- "#b0790b"
identified_metabolites[identified_metabolites$temperature == 5, "colour"] <- "#1aa7d4"

identified_metabolites$intensity <- as.numeric(identified_metabolites$intensity)

Metabolites more abundant in WN

identified_metabolites %>% 
  filter(name %in% c("2-Aminobenzoic acid", "L-Glutamic acid",
                     "DL-Methionine sulfoxide", "N6-Acetyl-L-lysine",
                     "D-Pantothenic acid", "Pyridoxal" )) %>%
  filter(condition %in% c("SD_TF", "WN_TF")) %>%
  ggplot(aes(y=intensity, x=condition, group=condition)) +
  geom_boxplot(aes(fill=fill, colour=colour)) +
  scale_fill_identity() +
  scale_color_identity() +
  theme(strip.text = element_text(face = "bold", size=12),
        axis.title.x = element_blank()) +
  scale_y_continuous(labels = function(x) format(x, scientific = TRUE), limits = c(0,NA), breaks = extended_breaks(n=5)) +
  facet_wrap(~name, scale="free", ncol=2) -> plot_wn


print(plot_wn)

ggsave(plot = plot_wn, filename = "../figures/metabolites_WN.tiff", dpi = 300, width = 8, height = 6, bg="white")

Metabolites more abundant in SD

identified_metabolites %>% filter(name %in% c("L-Isoleucine", "Acetyl-L-carnitine",
                                                   "Butyryl-L-carnitine",
                                                   "Isovaleryl-L-carnitine")) %>%
  filter(condition %in% c("SD_TF", "WN_TF")) %>%
  ggplot(aes(y=intensity, x=condition, group=condition)) +
  geom_boxplot(aes(fill=fill, colour=colour)) +
  scale_fill_identity() +
  scale_color_identity() +
  theme(strip.text = element_text(face = "bold", size=12),
        axis.title.x = element_blank()) +
  scale_y_continuous(labels = function(x) format(x, scientific = TRUE), limits = c(0,NA), breaks = extended_breaks(n=5)) +
  facet_wrap(~name, scale="free", ncol=2) -> plot_sd

print(plot_sd)

ggsave(plot = plot_sd, filename = "../figures/metabolites_SD.tiff", dpi = 300, width = 8, height = 4, bg="white")

Session informations

sessionInfo()
R version 4.3.1 (2023-06-16 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 11 x64 (build 26100)

Matrix products: default


locale:
[1] LC_COLLATE=French_France.utf8  LC_CTYPE=French_France.utf8    LC_MONETARY=French_France.utf8 LC_NUMERIC=C                   LC_TIME=French_France.utf8    

time zone: Europe/Paris
tzcode source: internal

attached base packages:
 [1] splines   stats4    grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] rlang_1.1.3                 lubridate_1.9.3             forcats_1.0.0               stringr_1.5.1               dplyr_1.1.4                 purrr_1.0.2                 readr_2.1.5                 tidyr_1.3.1                 tidyverse_2.0.0             cplm_0.7-12                
[11] Matrix_1.6-5                coda_0.19-4.1               compositions_2.0-8          ClassDiscovery_3.4.0        oompaBase_3.2.9             cluster_2.1.6               BiocManager_1.30.22         data.table_1.15.2           FactoMineR_2.10             ggh4x_0.2.8                
[21] knitr_1.45                  pheatmap_1.0.12             rgl_1.3.1                   scales_1.3.0                tibble_3.2.1                vegan_2.6-4                 lattice_0.22-5              permute_0.9-7               VennDiagram_1.7.3           futile.logger_1.4.3        
[31] MTXmodel_1.2.4              DESeq2_1.40.2               SummarizedExperiment_1.30.2 Biobase_2.60.0              MatrixGenerics_1.12.3       matrixStats_1.2.0           GenomicRanges_1.52.0        GenomeInfoDb_1.36.4         IRanges_2.34.1              S4Vectors_0.38.2           
[41] BiocGenerics_0.46.0         ggpubr_0.6.0                ggplot2_3.4.3               devtools_2.4.5              usethis_2.2.3              

loaded via a namespace (and not attached):
  [1] later_1.3.2             bitops_1.0-7            cellranger_1.1.0        lpsymphony_1.30.0       lifecycle_1.0.4         rstatix_0.7.2           MASS_7.3-60.0.1         oompaData_3.1.3         flashClust_1.01-2       backports_1.4.1         magrittr_2.0.3          sass_0.4.8             
 [13] rmarkdown_2.26          jquerylib_0.1.4         yaml_2.3.8              remotes_2.4.2.1         httpuv_1.6.14           sessioninfo_1.2.2       pkgbuild_1.4.3          cowplot_1.1.3.9000      bayesm_3.1-6            DBI_1.2.2               minqa_1.2.6             RColorBrewer_1.1-3     
 [25] multcomp_1.4-25         abind_1.4-5             pkgload_1.3.4           zlibbioc_1.46.0         RCurl_1.98-1.14         TH.data_1.1-2           tensorA_0.36.2.1        sandwich_3.1-0          GenomeInfoDbData_1.2.11 ggrepel_0.9.5           tweedie_2.3.5           codetools_0.2-19       
 [37] getopt_1.20.4           DelayedArray_0.26.7     DT_0.32                 tidyselect_1.2.1        farver_2.1.2            base64enc_0.1-3         jsonlite_1.8.8          ellipsis_0.3.2          survival_3.5-8          emmeans_1.10.0          systemfonts_1.0.6       tools_4.3.1            
 [49] ragg_1.3.0              Rcpp_1.0.12             glue_1.7.0              gridExtra_2.3           xfun_0.42               mgcv_1.9-1              withr_3.0.1             formatR_1.14            fastmap_1.1.1           fansi_1.0.6             digest_0.6.35           timechange_0.3.0       
 [61] R6_2.5.1                mime_0.12               estimability_1.5        textshaping_0.3.7       colorspace_2.1-0        utf8_1.2.4              generics_0.1.3          robustbase_0.99-2       htmlwidgets_1.6.4       S4Arrays_1.0.6          scatterplot3d_0.3-44    pkgconfig_2.0.3        
 [73] gtable_0.3.5            XVector_0.40.0          pcaPP_2.0-4             htmltools_0.5.7         carData_3.0-5           profvis_0.3.8           multcompView_0.1-10     leaps_3.1               optparse_1.7.4          lambda.r_1.2.4          rstudioapi_0.15.0       tzdb_0.4.0             
 [85] reshape2_1.4.4          nlme_3.1-164            cachem_1.0.8            zoo_1.8-12              parallel_4.3.1          miniUI_0.1.1.1          pillar_1.9.0            vctrs_0.6.5             urlchecker_1.0.1        promises_1.2.1          car_3.1-2               xtable_1.8-4           
 [97] evaluate_0.23           mvtnorm_1.2-4           cli_3.6.1               locfit_1.5-9.9          compiler_4.3.1          futile.options_1.0.1    crayon_1.5.2            ggsignif_0.6.4          labeling_0.4.3          mclust_6.1              plyr_1.8.9              fs_1.6.3               
[109] stringi_1.8.3           BiocParallel_1.34.2     munsell_0.5.1           hms_1.1.3               statmod_1.5.0           shiny_1.8.0             highr_0.10              broom_1.0.5             memoise_2.0.1           bslib_0.6.1             biglm_0.9-2.1           DEoptimR_1.1-3         
[121] readxl_1.4.3           
LS0tDQp0aXRsZTogIk1ldGFib2xvbWljcyBhbmQgTWV0YXRyYW5zY3JpcHRvbWljIGFuYWx5c2VzIG9mIGEgc3ludGhldGljIGNsb3VkIGNvbnNvcnRpdW0uIg0KYXV0aG9yOiAiRG9taXRpbGxlIEphcnJpZ2UiDQpkYXRlOiAnYHIgU3lzLkRhdGUoKWAnDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgc2VsZl9jb250YWluZWQ6IHllcw0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuDQogICAgdGhlbWU6IGNlcnVsZWFuDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogImhpZGUiDQogIHBkZl9kb2N1bWVudDoNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDMNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCi0tLQ0KDQpgYGB7ciBzZXR0aW5ncywgaW5jbHVkZT1GQUxTRSwgZWNobz1GQUxTRSwgZXZhbD1UUlVFfQ0Kb3B0aW9ucyh3aWR0aCA9IDMwMCkNCiMgb3B0aW9ucyhlbmNvZGluZyA9ICdVVEYtOCcpDQprbml0cjo6b3B0c19jaHVuayRzZXQoDQogIGZpZy53aWR0aCA9IDksIGZpZy5oZWlnaHQgPSA5LCANCiAgI2ZpZy5wYXRoID0gJ0M6L1VzZXJzL0RvbWl0aWxsZS9TZWFmaWxlL3Byb2pldHMvTUVUQUNMT1VEL21vY2tfY29tbXVuaXRpZXMvZmlndXJlcy8nLA0KICAjZmlnLnBhdGggPSAnQzovVXNlcnMvZG9taXQvU2VhZmlsZS9wcm9qZXRzL01FVEFDTE9VRC90cmFuc2NyaXB0b21pY3MvbW9ja19jb21tdW5pdGllcy9maWd1cmVzLycsDQogIGZpZy5wYXRoID0gIkM6L1VzZXJzL2RqYXJyaWdlL0Rlc2t0b3AvRG9taXRpbGxlL3Byb2pldHMvQW5jaWVuc19wcm9qZXRzL01FVEFDTE9VRC9maWd1cmVzIiwNCiAgZmlnLmFsaWduID0gImNlbnRlciIsIA0KICBzaXplID0gInNtYWxsIiwgDQogIGVjaG8gPSBUUlVFLCANCiAgZXZhbCA9IFRSVUUsIA0KICB3YXJuaW5nID0gRkFMU0UsIA0KICBtZXNzYWdlID0gRkFMU0UsIA0KICByZXN1bHRzID0gVFJVRSwgDQogIGNvbW1lbnQgPSAiIikNCg0Kb3B0aW9ucyhzY2lwZW4gPSAxMikgIyMgTWF4IG51bWJlciBvZiBkaWdpdHMgZm9yIG5vbi1zY2llbnRpZmljIG5vdGF0aW9uDQojIGtuaXRyOjphc2lzX291dHB1dCgiXFxmb290bm90ZXNpemUiKQ0KYGBgDQoNCmBgYHtyIHNldF93b3JraW5nX2RpcmVjdG9yeX0NCiNzZXR3ZCgiQzovVXNlcnMvRG9taXRpbGxlL1NlYWZpbGUvcHJvamV0cy9NRVRBQ0xPVUQvbW9ja19jb21tdW5pdGllcy9zY3JpcHRzIikNCiNzZXR3ZCgiQzovVXNlcnMvZG9taXQvU2VhZmlsZS9wcm9qZXRzL01FVEFDTE9VRC90cmFuc2NyaXB0b21pY3MvbW9ja19jb21tdW5pdGllcy9zY3JpcHRzIikNCnNldHdkKCJDOi9Vc2Vycy9kamFycmlnZS9EZXNrdG9wL0RvbWl0aWxsZS9wcm9qZXRzL0FuY2llbnNfcHJvamV0cy9NRVRBQ0xPVUQvc2NyaXB0cy8iKQ0KDQpgYGANCg0KIyBMaWJyYXJpZXMNCg0KYGBge3IgbGlicmFyaWVzLCBlY2hvPUZBTFNFLCBldmFsPVRSVUV9DQoNCg0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJkZXZ0b29scyIsIHF1aWV0bHkgPSBUUlVFKSkNCiAgICBpbnN0YWxsLnBhY2thZ2VzKGRldnRvb2xzKQ0KICBsaWJyYXJ5KCJkZXZ0b29scyIsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCg0KDQpsaXN0X2xpYl92ZXIgPC0gbGlzdChjKCJzdGF0cyIpLCAgYygiZ3JpZCIpLCBjKCJ1dGlscyIpLCBjKCJncmFwaGljcyIpLCANCiAgICAgICAgICAgICAgICAgICAgIGMoImdncGxvdDIiLCAiMy40LjMiKSwgYygiZ2dwdWJyIiwgIjAuNi4wIiksDQogICAgICAgICAgICAgICAgICAgICBjKCJERVNlcTIiLCAiMS40MC4yIiksIGMoIk1UWG1vZGVsIiwgIjEuMi40IiksIA0KICAgICAgICAgICAgICAgICAgICAgYygiVmVubkRpYWdyYW0iLCAiMS43LjMiKSwgYygidmVnYW4iLCAiMi42LTQiKSwNCiAgICAgICAgICAgICAgICAgICAgIGMoInRpYmJsZSIsICIzLjIuMSIpLCBjKCJzY2FsZXMiLCAiMS4zLjAiKSwNCiAgICAgICAgICAgICAgICAgICAgIGMoIlM0VmVjdG9ycyIsICIwLjM4LjIiKSwgYygicmdsIiwgIjEuMy4xIiksDQogICAgICAgICAgICAgICAgICAgICBjKCJwaGVhdG1hcCIsICIxLjAuMTIiKSwgYygia25pdHIiLCAiMS40NSIpLA0KICAgICAgICAgICAgICAgICAgICAgYygiZ2doNHgiLCAiMC4yLjgiKSwgYygiRmFjdG9NaW5lUiIsICIyLjEwIiksDQogICAgICAgICAgICAgICAgICAgICBjKCJkYXRhLnRhYmxlIiwgIjEuMTUuMiIpLCBjKCJCaW9jTWFuYWdlciIsICIxLjMwLjIyIiksDQogICAgICAgICAgICAgICAgICAgICBjKCJDbGFzc0Rpc2NvdmVyeSIsICIzLjQuMCIpLCBjKCJjb21wb3NpdGlvbnMiLCAiMi4wLTgiKSwNCiAgICAgICAgICAgICAgICAgICAgIGMoImNwbG0iLCAiMC43LTEyIiksDQogICAgICAgICAgICAgICAgICAgICBjKCJ0aWR5dmVyc2UiLCAiMi4wLjAiKSwgYygicmxhbmciLCAiMS4xLjMiKQ0KICAgICAgICAgICAgICAgICAgICAgKQ0KDQpmb3IgKGxpYiBpbiBsaXN0X2xpYl92ZXIpew0KICBpZiAoIXJlcXVpcmVOYW1lc3BhY2UobGliW1sxXV0sIHF1aWV0bHkgPSBUUlVFKSkNCiAgICAgIGRldnRvb2xzOjppbnN0YWxsX3ZlcnNpb24obGliW1sxXV0sIGxpYltbMl1dKQ0KICAgIGxpYnJhcnkobGliW1sxXV0sIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCn0NCg0KDQppZiAoIXJlcXVpcmUoIk1UWG1vZGVsIiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgew0KICAgIGRldnRvb2xzOmluc3RhbGxfZ2l0aHViKCdiaW9iYWtlcnkvTVRYX21vZGVsJykNCn0NCmxpYnJhcnkoIk1UWG1vZGVsIikNCg0KDQojIHRvIGluY2x1ZGUgM0QgcGxvdHMgaW4gaHRtbCByZXBvcnQNCmtuaXRyOjprbml0X2hvb2tzJHNldCh3ZWJnbCA9IGhvb2tfd2ViZ2wpDQoNCmBgYA0KDQoNCiMgVmFyaWFibGVzDQoNCmBgYHtyIHZhcmlhYmxlc30NCnZlY3RfQ09HX2NhdGVnb3J5X2xvbmcgPC0gYygiQSIgPSAiQTogUk5BIHByb2Nlc3NpbmcgYW5kIG1vZGlmaWNhdGlvbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkIiID0gIkI6IENocm9tYXRpbiBTdHJ1Y3R1cmUgYW5kIGR5bmFtaWNzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQyIgPSAiQzogRW5lcmd5IHByb2R1Y3Rpb24gYW5kIGNvbnZlcnNpb24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEIiA9ICJEOiBDZWxsIGN5Y2xlIGNvbnRyb2wsIGNlbGwgZGl2aXNpb24sIGNocm9tb3NvbWUgcGFydGl0aW9uaW5nIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRSIgPSAiRTogQW1pbm8gQWNpZCB0cmFuc3BvcnQgYW5kIG1ldGFib2xpc20iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGIiA9ICJGOiBOdWNsZW90aWRlIHRyYW5zcG9ydCBhbmQgbWV0YWJvbGlzbSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkciID0gIkc6IENhcmJvaHlkcmF0ZSB0cmFuc3BvcnQgYW5kIG1ldGFib2xpc20iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIIiA9ICJIOiBDb2VuenltZSB0cmFuc3BvcnQgYW5kIG1ldGFib2xpc20iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJIiA9ICJJOiBMaXBpZCB0cmFuc3BvcnQgYW5kIG1ldGFib2xpc20iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJKIiA9ICJKOiBUcmFuc2xhdGlvbiwgcmlib3NvbWFsIHN0cnVjdHVyZSBhbmQgYmlvZ2VuZXNpcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIksiID0gIks6IFRyYW5zY3JpcHRpb24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMIiA9ICJMOiBSZXBsaWNhdGlvbiwgcmVjb21iaW5hdGlvbiBhbmQgcmVwYWlyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTSIgPSAiTTogQ2VsbCB3YWxsL21lbWJyYW5lL2VudmVsb3BlIGJpb2dlbmVzaXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOIiA9ICJOOiBDZWxsIG1vdGlsaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTyIgPSAiTzogUG9zdC10cmFuc2xhdGlvbmFsIG1vZGlmaWNhdGlvbiwgcHJvdGVpbiB0dXJub3ZlciwgY2hhcGVyb25lcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlAiID0gIlA6IElub3JnYW5pYyBpb24gdHJhbnNwb3J0IGFuZCBtZXRhYm9saXNtIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUSIgPSAiUTogU2Vjb25kYXJ5IG1ldGFib2xpdGVzIGJpb3N5bnRoZXNpcywgdHJhbnNwb3J0IGFuZCBjYXRhYm9saXNtIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVCIgPSAiVDogU2lnbmFsIFRyYW5zZHVjdGlvbiBtZWNoYW5pc21zIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVSIgPSAiVTogSW50cmFjZWxsdWxhciB0cmFmZmlja2luZywgc2VjcmV0aW9uIGFuZCB2ZXNpY3VsYXIgdHJhbnNwb3J0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiViIgPSAiVjogRGVmZW5zZSBtZWNoYW5pc21zIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVyIgPSAiVzogRXh0cmFjZWxsdWxhciBzdHJ1Y3R1cmVzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiWCIgPSAiWDogTW9iaWxvbWU6IHByb3BoYWdlcywgdHJhbnNwb3NvbnMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJZIiA9ICJZOiBOdWNsZWFyIHN0cnVjdHVyZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIloiID0gIlo6IEN5dG9za2VsZXRvbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlIiID0gIlI6IEdlbmVyYWwgZnVuY3Rpb25hbCBwcmVkaWN0aW9uIG9ubHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTIiA9ICJTOiBGdW5jdGlvbiB1bmtub3duIiAjLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgIi0iID0gIi06IE90aGVyIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICkNCg0KDQpDT0dfY29sb3VycyA8LSBodWVfcGFsKCkobGVuZ3RoKHZlY3RfQ09HX2NhdGVnb3J5X2xvbmcpKQ0KbmFtZXMoQ09HX2NvbG91cnMpIDwtIHZlY3RfQ09HX2NhdGVnb3J5X2xvbmcNCg0Kc3BlY2llc19jb2xvdXJzIDwtIGMoIkQuaHVuZ2FyaWNhIiA9ICIjZTY2MTAxIiwgIlAuZ3JhbWluaXMiID0gIiNmZGI4NjMiLCANCiAgICAgICAgICAgICAgICAgICAgICJQLnN5cmluZ2FlIiA9ICIjYjJhYmQyIiwgIlIuZW5jbGVuc2lzIiA9ICIjNWUzYzk5IikNCmBgYA0KDQojIEZ1bmN0aW9ucw0KDQpgYGB7ciBmdW5jdGlvbnN9DQoNCmNvbXB1dGVfZGVzZXEyX2FuYWx5c2lzID0gZnVuY3Rpb24obXlEYXRhLCBzYW1wbGVfZGF0YSwgc3Vic2V0X3Zhcj1GQUxTRSwgc2VsZWN0PUZBTFNFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RfY29sLCByZWYsIHRlc3RlZCl7DQogIGRhdGEgPC0gbXlEYXRhDQogIHNhbXBsZSA8LSBzYW1wbGVfZGF0YQ0KICBpZiAoKHN1YnNldF92YXIgIT0gRkFMU0UpICYgKHNlbGVjdCAhPSBGQUxTRSkpew0KICAgIHNhbXBsZSAlPiUgZmlsdGVyKCEhYXMubmFtZShzdWJzZXRfdmFyKSA9PSBzZWxlY3QpIC0+IHNhbXBsZQ0KICB9DQogIA0KICBzYW1wbGVbW2NvbnRyYXN0X2NvbF1dIDwtIGZhY3RvcihzYW1wbGVbW2NvbnRyYXN0X2NvbF1dKQ0KICBkYXRhIDwtIGRhdGFbcm93Lm5hbWVzKHNhbXBsZSldDQogIA0KICBkYXRhX21hdHJpeCA8LSByb3VuZChhcy5tYXRyaXgoZGF0YSkpDQogIGQgPSBmb3JtdWxhKHBhc3RlKCJ+IiwgIiAiLCBjb250cmFzdF9jb2wpKQ0KICANCiAgZGRzIDwtIERFU2VxRGF0YVNldEZyb21NYXRyaXgoY291bnREYXRhID0gZGF0YV9tYXRyaXgsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gc2FtcGxlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ24gPSBkKQ0KICBkZHMgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhkZHMpDQogIGRkcyA8LSBERVNlcShkZHMpDQogIHJlc3VsdHNOYW1lcyhkZHMpDQogIHJlc0RFU2VxIDwtIHJlc3VsdHMoZGRzLCBjb250cmFzdCA9IGMoY29udHJhc3RfY29sLCB0ZXN0ZWQsIHJlZiksDQogICAgICAgICAgICAgICAgICAgICAgaW5kZXBlbmRlbnRGaWx0ZXJpbmcgPSBUUlVFLCBhbHBoYT0wLjEpDQogIA0KICByZXNERVNlcSA8LSByZXNERVNlcVtvcmRlcihyZXNERVNlcSRwYWRqKSxdDQogIHJlcyA8LSBkYXRhLmZyYW1lKHJlc0RFU2VxKQ0KICByZXMkZ2VuZSA9IHJvdy5uYW1lcyhyZXMpDQogIHJlcyRjb25kaXRpb24gPSBzZWxlY3QNCiAgcmVzJFNBTVBMRV9DT01QQVJJU09OID0gcGFzdGUwKHRlc3RlZCwgIl9WU18iLCByZWYpIA0KICAjcmVzICU+JSBmaWx0ZXIocGFkaiA8IDAuMiAmIGFicyhsb2cyRm9sZENoYW5nZSkgPiAxKSAtPiByZXMNCiAgDQogIHJldHVybihyZXMpDQp9DQpgYGANCg0KIyBFeHBlcmltZW50YWwgc2V0dXANCg0KQ29tcGFyaXNvbiBvZiBhbiBhcnRpZmljaWFsIG1pY3JvYmlhbCBjb21tdW5pdHkgZ2VuZSBleHByZXNzaW9uIHVuZGVyIHR3byBjbG91ZC1saWtlIGNvbmRpdGlvbnM6IA0KDQogLSAqKnN1bW1lciBkYXkgKFNEKToqKiBsaWdodCwgMjUwwrVNIEgyTzIsIDE3wrBDIA0KDQogLSAqKndpbnRlciBuaWdodCAoV04pOioqIGRhcmssIG5vIGFkZGVkIEgyTzIsIDXCsEMNCg0KDQohW10oLi4vZmlndXJlcy9leHBlcmltZW50YWxfc2V0dXAucG5nKQ0KDQoNCiMgQmlvaW5mb3JtYXRpYyB3b3JrZmxvdyBhbmQgbWFwcGluZyBvdmVydmlldw0KDQpUaGUgbWV0YXRyYW5zY3JpcHRvbWljcyBkYXRhIHdhcyBwcm9jZXNzZWQgdXNpbmcgYSBjdXN0b20gbWFkZSBTbmFrZW1ha2Ugd29ya2Zsb3cuDQoNCiFbXSguLi9maWd1cmVzL21ldGFnZW5vbWljX2FuYWx5c2VzX2NvbW11bml0eTUuZHJhd2lvLnBuZykgDQoNClR3byBzZXF1ZW5jaW5nIHJ1bnMgd2VyZSBwZXJmb3JtZWQgYnkgR2Vub3NjcmVlbiAoTGlsbGUsIEZyYW5jZSkgYXMgdGhlIGZpcnN0IHJ1biBwcm9kdWNlZCByZWxhdGl2ZWx5IGxvdyBxdWFsaXR5IHJlYWRzLiBCb3RoIHJ1bnMgYXJlIGFkZGVkIGludG8gYSBzaW5nbGUgZGF0YXNldCBpbiBvdXIgYW5hbHlzZXMuDQoNCkFmdGVyIHF1YWxpdHkgY29udHJvbCBzdGVwcyBhbmQgcmVhZCBjbGVhbmluZyAoW3JlcG9ydF0oaHR0cHM6Ly9zZWFmaWxlLnVuaXN0cmEuZnIvZi82MWUxYzliZDk3ZjA0OWEyYTRmNC8/ZGw9MSkpIHJlbWFpbmluZyByUk5BIChub3QgZGVwbGV0ZWQgcHJpb3IgdG8gc2VxdWVuY2luZykgd2VyZSByZW1vdmVkIHdpdGggc29ydG1lUk5BLiBBcyBmdW5nYWwgclJOQSB3ZXJlIG5vdCBkZXBsZXRlZCBpbiBvdXIgbGlicmFyaWVzLCB0aGUgdmFzdCBtYWpvcml0eSBvZiBvdXIgcmVhZHMgY29ycmVzcG9uZCB0byAqRGlvc3plZ2lhKiAqaHVuZ2FyaWNhKiByUk5Bcy4NCg0KTm9uIHJpYm9zb21hbCBhbmQgcmlib3NvbWFsIFJOQXMgd2VyZSB0aGVuIG1hcHBlZCBzZXBhcmF0ZWx5IG9uIG91ciByZWZlcmVuY2UgZ2Vub21lcyB1c2luZyBTVEFSLg0KDQpGb3Igbm9uIHJSTkEgcmVhZHM6ICoqXH45MC05NSUgb2YgcmVhZHMgbWFwcGVkIGluIGJpb2xvZ2ljYWwgc2FtcGxlcyoqIChbc3VtbWFyeV0oaHR0cHM6Ly9zZWFmaWxlLnVuaXN0cmEuZnIvZi9kNGY1NWQ0YjYwMzQ0YzY0YmI0YS8pLiBJbiBibGFuayBzYW1wbGVzLCBhIGxhcmdlciBmcmFjdGlvbiBvZiByZWFkcyBhcmUgdW5tYXBwZWQuDQoNCkZldyByZWFkcyBhcmUgbWFwcGVkIG9uICpQLiBncmFtaW5pcyogUERELTEzYi0zIGdlbm9tZS4gSXQgd2lsbCBiZSBkaWZmaWN1bHQgdG8gZ2V0IHNpZ25pZmljYW50IHJlc3VsdHMgZm9yIHRoaXMgc3BlY2llcy4NCg0KTGFzdGx5LCBmb3IgZWFjaCBnZW5lIG9mIHRoZSBjb21tdW5pdHksIHJlYWQgY291bnRzIHdlcmUgb2J0YWluZWQgd2l0aCBmZWF0dXJlQ291bnRzLictTScgYW5kICctLWZyYWN0aW9uJyBvcHRpb25zIHdlcmUgdXNlZCB0byBjb3VudCBtdWx0aS1tYXBwaW5nIHJlYWRzIGZyYWN0aW9uYWxseSAoaWYgYSByZWFkIG1hcHMgb24geCBmZWF0dXJlczogZWFjaCBmZWF0dXJlIGdldHMgMS94IGNvdW50cykuDQoNCg0KIyBBbmFseXNlcw0KDQoNCiMjIyMjIExvYWQgY291bnRzIGFuZCBhbm5vdGF0aW9uIGRhdGENCg0KYGBge3IgbG9hZF9kYXRhfQ0KDQpjb3VudHNfdGFibGUgPC0gcmVhZC5jc3YoIi4uL3Jlc3VsdHMvYWxsX2NvdW50c19jb21tdW5pdHlfYXJ0aWZpY2lhbF9ub19yUk5BLnRzdiIsIHNlcCA9ICJcdCIsIHJvdy5uYW1lcyA9ICJHZW5laWQiKQ0KDQptZXRhZGF0YV90YWJsZSA8LSByZWFkLmNzdigiLi4vZGF0YS9tZXRhZGF0YS50eHQiLCBzZXAgPSAiXHQiLCByb3cubmFtZXMgPSAibmFtZSIpICMgcm93Lm5hbWVzID0gInNhbXBsZSINCg0KDQpjb3VudHNfdGFibGUgJT4lIHJlbmFtZSgiV05fVEZfMSIgPSAiU181QzEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICJXTl9URl8yIiA9ICJTXzVDMiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIldOX1RGXzMiID0gIlNfNUMzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJXTl9CTEsiID0gIlNfNUJMSyIsDQogICAgICAgICAgICAgICAgICAgICAgICAiU0RfVEZfMSIgPSAiU18xN0MxIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAiU0RfVEZfMiIgPSAiU18xN0MyIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAiU0RfVEZfMyIgPSAiU18xN0MzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJTRF9CTEsiID0gIlNfMTdCTEsiKSAtPiBjb3VudHNfdGFibGUNCg0KYW5ub3RhdGlvbl90YWJsZSA8LSByZWFkLmNzdigiLi4vZGF0YS9hbm5vdGF0aW9uc19maW5hbF9jb21tdW5pdHlfdXBkYXRlZC50c3YiLCBzZXA9Ilx0Iiwgcm93Lm5hbWVzID0gIkdlbmVpZCIpDQphbm5vdGF0aW9uX2FsbCA8LSByZWFkLmNzdigiLi4vZGF0YS9hbm5vdGF0aW9uc19maW5hbF9jb21tdW5pdHlfdXBkYXRlZC50c3YiLCBzZXA9Ilx0Iiwgcm93Lm5hbWVzID0gIkdlbmVpZCIpDQphbm5vdGF0aW9uX3RhYmxlX2xvbmcgPC0gcmVhZC5jc3YoIi4uL2RhdGEvYW5ub3RhdGlvbnNfZmluYWxfY29tbXVuaXR5X2xvbmcudHN2Iiwgc2VwPSJcdCIsIHJvdy5uYW1lcyA9ICJHZW5laWQiKQ0KDQojIyBhZGRlZCBqdWx5IDIwMjQNCmNvdW50c190YWJsZSA8LSBjb3VudHNfdGFibGVbaW50ZXJzZWN0KHJvd25hbWVzKGNvdW50c190YWJsZSksIHJvd25hbWVzKGFubm90YXRpb25fYWxsKSksXQ0KDQoNCg0KYW5ub3RhdGlvbl9kaW9odSA8LSByZWFkLmNzdigiLi4vZGF0YS9kaW9zemVnaWFfa2VnZy50c3YiLCBzZXA9Ilx0Iiwgcm93Lm5hbWVzID0gIkdlbmVpZCIpDQphbm5vdGF0aW9uX3BzZWdyIDwtIHJlYWQuY3N2KCIuLi9kYXRhL3BzZXVkb21vbmFzX2dyYW1pbmlzX2tlZ2cudHN2Iiwgc2VwPSJcdCIsIHJvdy5uYW1lcyA9ICJHZW5laWQiKQ0KYW5ub3RhdGlvbl9wc2VzeSA8LSByZWFkLmNzdigiLi4vZGF0YS9wc2V1ZG9tb25hc19zeXJpbmdhZV9rZWdnLnRzdiIsIHNlcD0iXHQiLCByb3cubmFtZXMgPSAiR2VuZWlkIikNCmFubm90YXRpb25fcmhvZW4gPC0gcmVhZC5jc3YoIi4uL2RhdGEvcmhvZG9jb2NjdXNfa2VnZy50c3YiLCBzZXA9Ilx0Iiwgcm93Lm5hbWVzID0gIkdlbmVpZCIpDQoNCmNoZW1fZGF0YV9tZXRhVCA8LSByZWFkLmNzdigiLi4vZGF0YS9mb3JtYWxkZWh5ZGVfZXZvbHV0aW9uX3RyYW5zY3JpcHRvbWljcy50eHQiLCBzZXA9Ilx0IikNCmNoZW1fZGF0YV9tZXRhQiA8LSByZWFkLmNzdigiLi4vZGF0YS9mb3JtYWxkZWh5ZGVfZXZvbHV0aW9uX21ldGFib2xvbWljcy50eHQiLCBzZXA9Ilx0IikNCg0KIyMgRGF0YSBmb3IgZmlndXJlDQoNCmFubm90YXRpb25fdGFibGVfZmlnIDwtIHJlYWR4bDo6cmVhZF9leGNlbCgiLi4vZGF0YS9UYWJsZV9TM19ERUdzX2Fubm90YXRpb25zLnhsc3giKQ0KcmVuYW1lKGFubm90YXRpb25fdGFibGVfZmlnLCAiQ09HX2NhdGVnb3J5IiA9ICJDT0cgY2F0ZWdvcnkiLCANCiAgICAgICAiQ09HX2NhdGVnb3J5X2xvbmciID0gIkNPRyBjYXRlZ29yeSBsb25nIiwNCiAgICAgICAiQ09HX3Byb2Nlc3MiID0gIkNPRyBwcm9jZXNzIikgLT4gYW5ub3RhdGlvbl90YWJsZV9maWcNCg0KbWV0YWJvbG9taWNzX2RmIDwtIHJlYWQuY3N2KCIuLi9kYXRhL21ldGFib2xvbWljcy50eHQiLCBzZXA9Ilx0Iiwgcm93Lm5hbWVzID0gMSkNCg0KIyBrZWVwIGEgdmVyc2lvbiBvZiB0aGUgbWV0YWJvbG9taWNzIGRhdGFzZXQgd2l0aCBhbGwgdGltZSBwb2ludHMNCm1ldGFib2xvbWljc19kZiAtPiBtZXRhYm9sb21pY3NfYWxsX3RpbWVzX2RmDQptZXRhYm9sb21pY3NfYWxsX3RpbWVzX2RmICU+JSB0KCkgJT4lIGRhdGEuZnJhbWUoKSAtPiBtZXRhYm9sb21pY3NfYWxsX3RpbWVzX2RmDQoNCm1ldGFib2xvbWljc19hbGxfdGltZXNfZGYgJT4lIHJlbmFtZSgiV05fVDBfMSIgPSAiUzVDX1QwXzEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV05fVDBfMiIgPSAiUzVDX1QwXzIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV05fVDBfMyIgPSAiUzVDX1QwXzMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRF9UMF8xIiA9ICJTMTdDX1QwXzEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0RfVDBfMiIgPSAiUzE3Q19UMF8yIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNEX1QwXzMiID0gIlMxN0NfVDBfMyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldOX1RGXzEiID0gIlM1Q19URl8xIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldOX1RGXzIiID0gIlM1Q19URl8yIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldOX1RGXzMiID0gIlM1Q19URl8zIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0RfVEZfMSIgPSAiUzE3Q19URl8xIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNEX1RGXzIiID0gIlMxN0NfVEZfMiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRF9URl8zIiA9ICJTMTdDX1RGXzMiKSAtPiBtZXRhYm9sb21pY3NfYWxsX3RpbWVzX2RmDQoNCm1ldGFib2xvbWljc19hbGxfdGltZXNfZGYgPC0gbWV0YWJvbG9taWNzX2FsbF90aW1lc19kZlssYygiV05fVDBfMSIsICJXTl9UMF8yIiwgIldOX1QwXzMiLCAiU0RfVDBfMSIsICJTRF9UMF8yIiwgIlNEX1QwXzMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIsICJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpXQ0KDQptZXRhZGF0YV90YWJsZV9tZXRhQl9hbGxfdGltZXMgPC0gcmVhZC5jc3YoIi4uL2RhdGEvbWV0YWRhdGFfbWV0YUIudHh0Iiwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gIm5hbWUiKSAjIHJvdy5uYW1lcyA9ICJzYW1wbGUiDQoNCiMgS2VlcCBmaW5hbCB0aW1lIHBvaW50cyBvbmx5LCBsaWtlIGZvciBtZXRhdHJhbnNjcmlwdG9taWNzDQptZXRhYm9sb21pY3NfZGYgICU+JSB0KCkgJT4lIA0KICBkYXRhLmZyYW1lKCkgJT4lIHNlbGVjdChzdGFydHNfd2l0aChjKCJTMTdDX1RGXyIsICJTNUNfVEZfIikpKSAtPiBtZXRhYm9sb21pY3NfZGYNCg0KDQptZXRhYm9sb21pY3NfZGYgJT4lIHJlbmFtZSgiV05fVEZfMSIgPSAiUzVDX1RGXzEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJXTl9URl8yIiA9ICJTNUNfVEZfMiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIldOX1RGXzMiID0gIlM1Q19URl8zIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRF9URl8xIiA9ICJTMTdDX1RGXzEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRF9URl8yIiA9ICJTMTdDX1RGXzIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRF9URl8zIiA9ICJTMTdDX1RGXzMiKSAtPiBtZXRhYm9sb21pY3NfZGYNCg0KbWV0YWJvbG9taWNzX2JveF9wbG90X2RmIDwtIHJlYWR4bDo6cmVhZF9leGNlbCgiLi4vcmVzdWx0cy9tZXRhYm9sb21pY3NfYW5ub3RhdGlvbl9ib3hwbG90Lnhsc3giKQ0KDQptZXRhYm9sb21pY3NfYW5ub3RhdGlvbnMgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCIuLi9yZXN1bHRzL1RhYmxlX1MyX01ldGFib2xpdGVzX2lkZW50aWZpZWQueGxzeCIsIG5fbWF4ID0gMjUpDQpgYGANCg0KIyMjIyMgUmVtb3ZhbCBvZiBibGFuayBzYW1wbGVzDQoNCmBgYHtyIHRha2luZ19vdXRfYmxrfQ0KDQpjb3VudHNfdGFibGUgPC0gY291bnRzX3RhYmxlWyxjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIsICJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpXQ0KbWV0YWRhdGFfdGFibGUgPC0gbWV0YWRhdGFfdGFibGVbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiLCAiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSxdDQogIA0KYGBgDQoNCiMjIENoZW1pY2FsIHByb3BlcnRpZXMgb2YgdGhlIHNhbXBsZXMgey50YWJzZXR9DQoNCiMjIyBGb3JtYWxkZWh5ZGUgZXZvbHV0aW9uDQoNCmBgYHtyIGNoZW1fcGxvdHNfZm9ybWFsZGVoeWRlfQ0KDQpjaGVtX2RhdGFfbWV0YVQkZXhwZXJpbWVudCA8LSAibWV0YVQiDQpjaGVtX2RhdGFfbWV0YUIkZXhwZXJpbWVudCA8LSAibWV0YUIiDQoNCmNoZW1fZGF0YSA8LSByYmluZChjaGVtX2RhdGFfbWV0YVQsIGNoZW1fZGF0YV9tZXRhQikNCg0KDQoNCiMjIE1ldGF0cmFuc2NyaXB0b21pY3MgZGF0YQ0KDQpjaGVtX2RhdGFbY2hlbV9kYXRhJGNvbG9yID09ICIjODlEREY4IiAmIGNoZW1fZGF0YSRleHBlcmltZW50ID09ICJtZXRhVCIsXSAtPiB0bXAxDQpncm91cF9ieSh0bXAxLCBzYW1wbGluZ190aW1lKSAlPiUgc3VtbWFyaXNlKGZvcm1hbGRlaHlkZV9tZWFuPW1lYW4oZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWFsZGVoeWRlX3NkPXNkKGZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsKSkgLT4gdG1wMQ0KdG1wMSRjb2xvciA8LSAiIzg5RERGOCINCnRtcDEkY29uZGl0aW9uIDwtICJXTiINCnRtcDEkY2F0ZWdvcnkgPC0gImJpb3RpY19XTiINCnRtcDEkZXhwZXJpbWVudCA8LSAibWV0YVQiDQoNCmNoZW1fZGF0YVtjaGVtX2RhdGEkY29sb3IgPT0gIiNGOEFEMTgiICYgY2hlbV9kYXRhJGV4cGVyaW1lbnQgPT0gIm1ldGFUIixdIC0+IHRtcDINCmdyb3VwX2J5KHRtcDIsIHNhbXBsaW5nX3RpbWUpICU+JSBzdW1tYXJpc2UoZm9ybWFsZGVoeWRlX21lYW49bWVhbihmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYWxkZWh5ZGVfc2Q9c2QoZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwpKSAtPiB0bXAyDQp0bXAyJGNvbG9yIDwtICIjRjhBRDE4Ig0KdG1wMiRjb25kaXRpb24gPC0gIlNEIg0KdG1wMiRjYXRlZ29yeSA8LSAiYmlvdGljX1NEIg0KdG1wMiRleHBlcmltZW50IDwtICJtZXRhVCINCg0KY2hlbV9kYXRhW2NoZW1fZGF0YSRjb2xvciA9PSAiI0E2QzFDQSIgJiBjaGVtX2RhdGEkZXhwZXJpbWVudCA9PSAibWV0YVQiLF0gLT4gdG1wMw0KZ3JvdXBfYnkodG1wMywgc2FtcGxpbmdfdGltZSkgJT4lIHN1bW1hcmlzZShmb3JtYWxkZWh5ZGVfbWVhbj1tZWFuKGZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hbGRlaHlkZV9zZD1zZChmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCkpIC0+IHRtcDMNCnRtcDMkY29sb3IgPC0gIiNBNkMxQ0EiDQp0bXAzJGNvbmRpdGlvbiA8LSAiV04iDQp0bXAzJGNhdGVnb3J5IDwtICJhYmlvdGljX1dOIg0KdG1wMyRleHBlcmltZW50IDwtICJtZXRhVCINCg0KY2hlbV9kYXRhW2NoZW1fZGF0YSRjb2xvciA9PSAiI0M0QjY5QiIgJiBjaGVtX2RhdGEkZXhwZXJpbWVudCA9PSAibWV0YVQiLF0gLT4gdG1wNA0KZ3JvdXBfYnkodG1wNCwgc2FtcGxpbmdfdGltZSkgJT4lIHN1bW1hcmlzZShmb3JtYWxkZWh5ZGVfbWVhbj1tZWFuKGZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hbGRlaHlkZV9zZD1zZChmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCkpIC0+IHRtcDQNCnRtcDQkY29sb3IgPC0gIiNDNEI2OUIiDQp0bXA0JGNvbmRpdGlvbiA8LSAiU0QiDQp0bXA0JGNhdGVnb3J5IDwtICJhYmlvdGljX1NEIg0KdG1wNCRleHBlcmltZW50IDwtICJtZXRhVCINCg0KIyMgTWV0YWJvbG9taWNzIGRhdGENCg0KY2hlbV9kYXRhW2NoZW1fZGF0YSRjb2xvciA9PSAiIzg5RERGOCIgJiBjaGVtX2RhdGEkZXhwZXJpbWVudCA9PSAibWV0YUIiLF0gLT4gdG1wNQ0KZ3JvdXBfYnkodG1wNSwgc2FtcGxpbmdfdGltZSkgJT4lIHN1bW1hcmlzZShmb3JtYWxkZWh5ZGVfbWVhbj1tZWFuKGZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hbGRlaHlkZV9zZD1zZChmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCkpIC0+IHRtcDUNCnRtcDUkY29sb3IgPC0gIiM4OURERjgiDQp0bXA1JGNvbmRpdGlvbiA8LSAiV04iDQp0bXA1JGNhdGVnb3J5IDwtICJiaW90aWNfV04iDQp0bXA1JGV4cGVyaW1lbnQgPC0gIm1ldGFCIg0KDQpjaGVtX2RhdGFbY2hlbV9kYXRhJGNvbG9yID09ICIjRjhBRDE4IiAmIGNoZW1fZGF0YSRleHBlcmltZW50ID09ICJtZXRhQiIsXSAtPiB0bXA2DQpncm91cF9ieSh0bXA2LCBzYW1wbGluZ190aW1lKSAlPiUgc3VtbWFyaXNlKGZvcm1hbGRlaHlkZV9tZWFuPW1lYW4oZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWFsZGVoeWRlX3NkPXNkKGZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsKSkgLT4gdG1wNg0KdG1wNiRjb2xvciA8LSAiI0Y4QUQxOCINCnRtcDYkY29uZGl0aW9uIDwtICJTRCINCnRtcDYkY2F0ZWdvcnkgPC0gImJpb3RpY19TRCINCnRtcDYkZXhwZXJpbWVudCA8LSAibWV0YUIiDQoNCmNoZW1fZGF0YVtjaGVtX2RhdGEkY29sb3IgPT0gIiNBNkMxQ0EiICYgY2hlbV9kYXRhJGV4cGVyaW1lbnQgPT0gIm1ldGFCIixdIC0+IHRtcDcNCmdyb3VwX2J5KHRtcDcsIHNhbXBsaW5nX3RpbWUpICU+JSBzdW1tYXJpc2UoZm9ybWFsZGVoeWRlX21lYW49bWVhbihmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYWxkZWh5ZGVfc2Q9c2QoZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwpKSAtPiB0bXA3DQp0bXA3JGNvbG9yIDwtICIjQTZDMUNBIg0KdG1wNyRjb25kaXRpb24gPC0gIldOIg0KdG1wNyRjYXRlZ29yeSA8LSAiYWJpb3RpY19XTiINCnRtcDckZXhwZXJpbWVudCA8LSAibWV0YUIiDQoNCmNoZW1fZGF0YVtjaGVtX2RhdGEkY29sb3IgPT0gIiNDNEI2OUIiICYgY2hlbV9kYXRhJGV4cGVyaW1lbnQgPT0gIm1ldGFCIixdIC0+IHRtcDgNCmdyb3VwX2J5KHRtcDgsIHNhbXBsaW5nX3RpbWUpICU+JSBzdW1tYXJpc2UoZm9ybWFsZGVoeWRlX21lYW49bWVhbihmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYWxkZWh5ZGVfc2Q9c2QoZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwpKSAtPiB0bXA4DQp0bXA4JGNvbG9yIDwtICIjQzRCNjlCIg0KdG1wOCRjb25kaXRpb24gPC0gIlNEIg0KdG1wOCRjYXRlZ29yeSA8LSAiYWJpb3RpY19TRCINCnRtcDgkZXhwZXJpbWVudCA8LSAibWV0YUIiDQoNCg0KIyMgTWVyZ2UgZGF0YQ0KDQpsaW5lX2RhdGEgPC0gcmJpbmQodG1wMSwgdG1wMiwgdG1wMywgdG1wNCwgdG1wNSwgdG1wNiwgdG1wNywgdG1wOCkNCnJtKHRtcDEsIHRtcDIsIHRtcDMsIHRtcDQsIHRtcDUsIHRtcDYsIHRtcDcsIHRtcDgpDQoNCg0KIyMgVGVzdCBkaWZmZXJlbmNlIGJldHdlZW4gYmlvdGljIGFuZCBhYmlvdGljDQoNCg0Ka3J1c2thbF9mb3JtYWxkZWh5ZGUgPC0gYygiIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5KGlmKGtydXNrYWwudGVzdCh4ID0gYyhjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDEgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjRjhBRDE4IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMSAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYmlvdGljX1NEIiwgMyksIHJlcCgiYWJpb3RpY19TRCIsIDMpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMiAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNGOEFEMTgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAyICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiI0M0QjY5QiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfU0QiLCAzKSwgcmVwKCJhYmlvdGljX1NEIiwgMykpDQogICAgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5KGlmKGtydXNrYWwudGVzdCh4ID0gYyhjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDMgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjRjhBRDE4IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMyAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYmlvdGljX1NEIiwgMyksIHJlcCgiYWJpb3RpY19TRCIsIDMpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMSAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNGOEFEMTgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAxICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0M0QjY5QiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfU0QiLCAzKSwgcmVwKCJhYmlvdGljX1NEIiwgMykpDQogICAgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAyICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0Y4QUQxOCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDIgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQzRCNjlCIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19TRCIsIDMpLCByZXAoImFiaW90aWNfU0QiLCAzKSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMyAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNGOEFEMTgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAzICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0M0QjY5QiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfU0QiLCAzKSwgcmVwKCJhYmlvdGljX1NEIiwgMykpDQogICAgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5KGlmKGtydXNrYWwudGVzdCh4ID0gYyhjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDUgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjRjhBRDE4IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gNSAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYmlvdGljX1NEIiwgMyksIHJlcCgiYWJpb3RpY19TRCIsIDMpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMSAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiM4OURERjgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAxICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiI0E2QzFDQSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfV04iLCAzKSwgcmVwKCJhYmlvdGljX1dOIiwgMykpDQogICAgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAyICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiIzg5RERGOCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDIgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjQTZDMUNBIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19XTiIsIDMpLCByZXAoImFiaW90aWNfV04iLCAzKSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMyAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiM4OURERjgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAzICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiI0E2QzFDQSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfV04iLCAzKSwgcmVwKCJhYmlvdGljX1dOIiwgMykpDQogICAgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAxICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiIzg5RERGOCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDEgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQTZDMUNBIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19XTiIsIDMpLCByZXAoImFiaW90aWNfV04iLCAzKSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpICwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5KGlmKGtydXNrYWwudGVzdCh4ID0gYyhjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDIgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjODlEREY4IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMiAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNBNkMxQ0EiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYmlvdGljX1dOIiwgMyksIHJlcCgiYWJpb3RpY19XTiIsIDMpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAzICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiIzg5RERGOCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDMgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQTZDMUNBIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19XTiIsIDMpLCByZXAoImFiaW90aWNfV04iLCAzKSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gNSAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiM4OURERjgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSA1ICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0E2QzFDQSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfV04iLCAzKSwgcmVwKCJhYmlvdGljX1dOIiwgMykpDQogICAgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKQ0KKQ0KDQojIyBUZXN0IGRpZmZlcmVuY2UgYmV0d2VlbiB0aW1lIDAgYW4gdGhlIG90aGVyIHRpbWUgcG9pbnRzDQoNCiMga3J1c2thbF9mb3JtYWxkZWh5ZGUgPC0gYygiIiwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAxICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjRjhBRDE4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNGOEFEMTgiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19TRF9URl8xIiwgMyksIHJlcCgiYmlvdGljX1NEXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSAsDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMiAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiI0Y4QUQxOCIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjRjhBRDE4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfU0RfVEZfMiIsIDMpLCByZXAoImJpb3RpY19TRF8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMyAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiI0Y4QUQxOCIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjRjhBRDE4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfU0RfVEZfMyIsIDMpLCByZXAoImJpb3RpY19TRF8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICAiIiwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAxICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjRjhBRDE4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNGOEFEMTgiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19TRF9URl8xIiwgMyksIHJlcCgiYmlvdGljX1NEXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSAsDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMiAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0Y4QUQxOCIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjRjhBRDE4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfU0RfVEZfMiIsIDMpLCByZXAoImJpb3RpY19TRF8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMyAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0Y4QUQxOCIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjRjhBRDE4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfU0RfVEZfMyIsIDMpLCByZXAoImJpb3RpY19TRF8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gNSAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0Y4QUQxOCIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjRjhBRDE4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfU0RfNSIsIDMpLCByZXAoImJpb3RpY19TRF8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICAiIiwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAxICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjODlEREY4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiM4OURERjgiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19XTl9URl8xIiwgMyksIHJlcCgiYmlvdGljX1dOXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSAsDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMiAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiIzg5RERGOCIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjODlEREY4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfV05fVEZfMiIsIDMpLCByZXAoImJpb3RpY19XTl8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMyAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiIzg5RERGOCIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjODlEREY4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfV05fVEZfMyIsIDMpLCByZXAoImJpb3RpY19XTl8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICAiIiwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAxICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjODlEREY4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiM4OURERjgiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19XTl9URl8xIiwgMyksIHJlcCgiYmlvdGljX1dOXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSAsDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMiAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiIzg5RERGOCIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjODlEREY4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfV05fVEZfMiIsIDMpLCByZXAoImJpb3RpY19XTl8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMyAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiIzg5RERGOCIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjODlEREY4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfV05fVEZfMyIsIDMpLCByZXAoImJpb3RpY19XTl8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICANCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSA1ICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjODlEREY4IiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiM4OURERjgiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19XTl81IiwgMyksIHJlcCgiYmlvdGljX1dOXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKQ0KIyAgICAgICAgICAgICAgICAgICAgICApDQoNCmtydXNrYWxfZGYgPC0gZGF0YS5mcmFtZSh0aW1lID0gcmVwKGMoMCwgMSwgMiwgMywgMCwgMSwgMiwgMywgNSksIDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IHJlcCgwLCAxOCksDQogICAgICAgICAgICAgICAgICAgICAgICAgZXhwZXJpbWVudCA9IHJlcChjKHJlcCgibWV0YUIiLCA0KSwgcmVwKCJtZXRhVCIsIDUpKSwgMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgY29uZGl0aW9uID0gYyhyZXAoIlNEIiwgOSksIHJlcCgiV04iLCA5KSksDQogICAgICAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcnkgPSBjKHJlcCgiY29tbXVuaXR5IFNEIiwgOSksIHJlcCgiY29tbXVuaXR5IFdOIiwgOSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gYyhyZXAoIiNGOEFEMTgiLCA5KSwgcmVwKCIjODlEREY4IiwgOSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZSA9IGtydXNrYWxfZm9ybWFsZGVoeWRlKQ0KDQoNCg0KIyBrcnVza2FsX2Zvcm1hbGRlaHlkZV9hYmlvIDwtIGMoIiIsDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMSAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiI0M0QjY5QiIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJhYmlvdGljX1NEX1RGXzEiLCAzKSwgcmVwKCJhYmlvdGljX1NEXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSAsDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMiAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiI0M0QjY5QiIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJhYmlvdGljX1NEX1RGXzIiLCAzKSwgcmVwKCJhYmlvdGljX1NEXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAzICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImFiaW90aWNfU0RfVEZfMyIsIDMpLCByZXAoImFiaW90aWNfU0RfMCIsIDMpKQ0KIyAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgIiIsDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMSAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0M0QjY5QiIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJhYmlvdGljX1NEX1RGXzEiLCAzKSwgcmVwKCJhYmlvdGljX1NEXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSAsDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMiAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0M0QjY5QiIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJhYmlvdGljX1NEX1RGXzIiLCAzKSwgcmVwKCJhYmlvdGljX1NEXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAzICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImFiaW90aWNfU0RfVEZfMyIsIDMpLCByZXAoImFiaW90aWNfU0RfMCIsIDMpKQ0KIyAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgdHJ5KGlmKGtydXNrYWwudGVzdCh4ID0gYyhjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDUgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMCAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0M0QjY5QiIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYWJpb3RpY19TRF81IiwgMyksIHJlcCgiYWJpb3RpY19TRF8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICAiIiwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAxICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjQTZDMUNBIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNBNkMxQ0EiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImFiaW90aWNfV05fVEZfMSIsIDMpLCByZXAoImFiaW90aWNfV05fMCIsIDMpKQ0KIyAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpICwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAyICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjQTZDMUNBIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNBNkMxQ0EiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImFiaW90aWNfV05fVEZfMiIsIDMpLCByZXAoImFiaW90aWNfV05fMCIsIDMpKQ0KIyAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgdHJ5KGlmKGtydXNrYWwudGVzdCh4ID0gYyhjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDMgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNBNkMxQ0EiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMCAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiI0E2QzFDQSIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYWJpb3RpY19XTl9URl8zIiwgMyksIHJlcCgiYWJpb3RpY19XTl8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICAiIiwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAxICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQTZDMUNBIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNBNkMxQ0EiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImFiaW90aWNfV05fVEZfMSIsIDMpLCByZXAoImFiaW90aWNfV05fMCIsIDMpKQ0KIyAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpICwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAyICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQTZDMUNBIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNBNkMxQ0EiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImFiaW90aWNfV05fVEZfMiIsIDMpLCByZXAoImFiaW90aWNfV05fMCIsIDMpKQ0KIyAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgdHJ5KGlmKGtydXNrYWwudGVzdCh4ID0gYyhjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDMgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNBNkMxQ0EiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9ybWFsZGVoeWRlX3JhdGlvX3RvX2luaXRpYWwiXSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMCAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0E2QzFDQSIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYWJpb3RpY19XTl9URl8zIiwgMyksIHJlcCgiYWJpb3RpY19XTl8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gNSAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0E2QzFDQSIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3JtYWxkZWh5ZGVfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQTZDMUNBIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJhYmlvdGljX1dOXzUiLCAzKSwgcmVwKCJhYmlvdGljX1dOXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKQ0KIyAgICAgICAgICAgICAgICAgICAgICApDQoNCiMga3J1c2thbF9kZl9hYmlvIDwtIGRhdGEuZnJhbWUodGltZSA9IHJlcChjKDAsIDEsIDIsIDMsIDAsIDEsIDIsIDMsIDUpLCAyKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IHJlcCgxLjE1LCAxOCksDQojICAgICAgICAgICAgICAgICAgICAgICAgICBleHBlcmltZW50ID0gcmVwKGMocmVwKCJtZXRhQiIsIDQpLCByZXAoIm1ldGFUIiwgNSkpLCAyKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmRpdGlvbiA9IGMocmVwKCJTRCIsIDkpLCByZXAoIldOIiwgOSkpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcnkgPSBjKHJlcCgiYWJpb3RpYyBTRCIsIDkpLCByZXAoImFiaW90aWMgV04iLCA5KSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGMocmVwKCIjQzRCNjlCIiwgOSksIHJlcCgiI0E2QzFDQSIsIDkpKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZSA9IGtydXNrYWxfZm9ybWFsZGVoeWRlX2FiaW8pDQoNCg0KI2tydXNrIDwtIHJiaW5kKGtydXNrYWxfZGYsIGtydXNrYWxfZGZfYWJpbykNCmtydXNrIDwtIGtydXNrYWxfZGYNCg0KDQojIyBTZWdtZW50IGRhdGEgZm9yIHNhbXBsaW5nIHRpbWUNCg0Kc2VnbWVudF9kYXRhIDwtIGRhdGEuZnJhbWUoeCA9IGMoNCwgMCwgMy41KSwgeGVuZCA9IGMoNCwgMCwgMy41KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gYygtSW5mLCAtSW5mLCAtSW5mKSwgeWVuZCA9IGMoSW5mLCBJbmYsIEluZiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBleHBlcmltZW50ID0gYygibWV0YVQiLCAibWV0YUIiLCAibWV0YUIiKSkNCiAgDQpjaGVtX2RhdGEgJT4lIGdncGxvdCgpICsNCiAgZ2VvbV9wb2ludChhZXMoeD1zYW1wbGluZ190aW1lLCB5PWZvcm1hbGRlaHlkZV9yYXRpb190b19pbml0aWFsLCBjb2xvcj1jb2xvcikpICsNCiAgeWxpbShjKC0wLjEsIDEuMikpICsNCiAgeGxpbShjKDAsIDUpKSArDQogIHNjYWxlX2NvbG91cl9pZGVudGl0eSgiY2F0ZWdvcnkiLCBsYWJlbHMgPSBjKCJjb21tdW5pdHkgV04iLCAiYWJpb3RpYyBXTiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJhYmlvdGljIFNEIiwgImNvbW11bml0eSBTRCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlPSJsZWdlbmQiKSArDQogIHNjYWxlX2ZpbGxfaWRlbnRpdHkoKSArDQogIHlsYWIobGFiZWwgPSAiUmVsYXRpdmUgZm9ybWFsZGVoeWRlIGV2b2x1dGlvbiIpICsNCiAgeGxhYihsYWJlbCA9ICJJbmN1YmF0aW9uIHRpbWUgKGgpIikgKw0KICAjIGZhY2V0X2dyaWQocm93cyA9IHZhcnMoZXhwZXJpbWVudCksIGNvbHMgPSB2YXJzKGNvbmRpdGlvbikpICsgIywgbnJvdz0yLCBuY29sPTINCiAgZmFjZXRfZ3JpZChyb3dzID0gdmFycyhjb25kaXRpb24pLCBjb2xzID0gdmFycyhleHBlcmltZW50KSwNCiAgICAgICAgICAgICBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGMoIm1ldGFUIiA9ICJNZXRhdHJhbnNjcmlwdG9taWNzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtZXRhQiIgPSAiTWV0YS1tZXRhYm9sb21pY3MiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0QiID0gIlNEIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldOIiA9ICJXTiIpKSkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0iI2Y0ZjRmNCIpKSArDQogIA0KICANCiAgZ2VvbV9wYXRoKGRhdGEgPSBsaW5lX2RhdGFbbGluZV9kYXRhJGNhdGVnb3J5ID09ICJiaW90aWNfU0QiLF0sIA0KICAgICAgICAgICAgYWVzKHggPSBzYW1wbGluZ190aW1lLCB5ID0gZm9ybWFsZGVoeWRlX21lYW4sIGNvbG9yID0gY29sb3IpLCANCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgDQogIGdlb21fcmliYm9uKGRhdGEgPSBsaW5lX2RhdGFbbGluZV9kYXRhJGNhdGVnb3J5ID09ICJiaW90aWNfU0QiLF0sIA0KICAgICAgICAgICAgICBhZXMoeCA9IHNhbXBsaW5nX3RpbWUsIA0KICAgICAgICAgICAgICAgICAgeW1pbiA9IGZvcm1hbGRlaHlkZV9tZWFuIC0gZm9ybWFsZGVoeWRlX3NkLA0KICAgICAgICAgICAgICAgICAgeW1heCA9IGZvcm1hbGRlaHlkZV9tZWFuICsgZm9ybWFsZGVoeWRlX3NkLA0KICAgICAgICAgICAgICAgICAgZmlsbCA9IGNvbG9yKSwgYWxwaGE9MC4yNSwgbGluZXdpZHRoPTAuMDUpICsNCiAgDQogIGdlb21fcGF0aChkYXRhID0gbGluZV9kYXRhW2xpbmVfZGF0YSRjYXRlZ29yeSA9PSAiYWJpb3RpY19TRCIsXSwgDQogICAgICAgICAgICBhZXMoeCA9IHNhbXBsaW5nX3RpbWUsIHkgPSBmb3JtYWxkZWh5ZGVfbWVhbiwgY29sb3IgPSBjb2xvciksIA0KICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyANCiAgZ2VvbV9yaWJib24oZGF0YSA9IGxpbmVfZGF0YVtsaW5lX2RhdGEkY2F0ZWdvcnkgPT0gImFiaW90aWNfU0QiLF0sIA0KICAgICAgICAgICAgICBhZXMoeCA9IHNhbXBsaW5nX3RpbWUsIA0KICAgICAgICAgICAgICAgICAgeW1pbiA9IGZvcm1hbGRlaHlkZV9tZWFuIC0gZm9ybWFsZGVoeWRlX3NkLA0KICAgICAgICAgICAgICAgICAgeW1heCA9IGZvcm1hbGRlaHlkZV9tZWFuICsgZm9ybWFsZGVoeWRlX3NkLA0KICAgICAgICAgICAgICAgICAgZmlsbCA9IGNvbG9yKSwgYWxwaGE9MC4yNSwgbGluZXdpZHRoPTAuMDUpICsNCiAgDQogIGdlb21fcGF0aChkYXRhID0gbGluZV9kYXRhW2xpbmVfZGF0YSRjYXRlZ29yeSA9PSAiYmlvdGljX1dOIixdLCANCiAgICAgICAgICAgIGFlcyh4ID0gc2FtcGxpbmdfdGltZSwgeSA9IGZvcm1hbGRlaHlkZV9tZWFuLCBjb2xvciA9IGNvbG9yKSwgDQogICAgICAgICAgICBsaW5ld2lkdGggPSAxKSArIA0KICBnZW9tX3JpYmJvbihkYXRhID0gbGluZV9kYXRhW2xpbmVfZGF0YSRjYXRlZ29yeSA9PSAiYmlvdGljX1dOIixdLCANCiAgICAgICAgICAgICAgYWVzKHggPSBzYW1wbGluZ190aW1lLCANCiAgICAgICAgICAgICAgICAgIHltaW4gPSBmb3JtYWxkZWh5ZGVfbWVhbiAtIGZvcm1hbGRlaHlkZV9zZCwNCiAgICAgICAgICAgICAgICAgIHltYXggPSBmb3JtYWxkZWh5ZGVfbWVhbiArIGZvcm1hbGRlaHlkZV9zZCwNCiAgICAgICAgICAgICAgICAgIGZpbGwgPSBjb2xvciksIGFscGhhPTAuMjUsIGxpbmV3aWR0aD0wLjA1KSArIA0KICANCiAgZ2VvbV9wYXRoKGRhdGEgPSBsaW5lX2RhdGFbbGluZV9kYXRhJGNhdGVnb3J5ID09ICJhYmlvdGljX1dOIixdLCANCiAgICAgICAgICAgIGFlcyh4ID0gc2FtcGxpbmdfdGltZSwgeSA9IGZvcm1hbGRlaHlkZV9tZWFuLCBjb2xvciA9IGNvbG9yKSwgDQogICAgICAgICAgICBsaW5ld2lkdGggPSAxKSArIA0KICBnZW9tX3JpYmJvbihkYXRhID0gbGluZV9kYXRhW2xpbmVfZGF0YSRjYXRlZ29yeSA9PSAiYWJpb3RpY19XTiIsXSwgDQogICAgICAgICAgICAgIGFlcyh4ID0gc2FtcGxpbmdfdGltZSwgDQogICAgICAgICAgICAgICAgICB5bWluID0gZm9ybWFsZGVoeWRlX21lYW4gLSBmb3JtYWxkZWh5ZGVfc2QsDQogICAgICAgICAgICAgICAgICB5bWF4ID0gZm9ybWFsZGVoeWRlX21lYW4gKyBmb3JtYWxkZWh5ZGVfc2QsDQogICAgICAgICAgICAgICAgICBmaWxsID0gY29sb3IpLCBhbHBoYT0wLjI1LCBsaW5ld2lkdGg9MC4wNSkgKyANCiAgDQogICMgcGxvdCBzaWduaWZpY2FuY2Ugc3RhcnMNCiAgZ2VvbV90ZXh0KGRhdGE9a3J1c2tba3J1c2skY2F0ZWdvcnkgPT0gImNvbW11bml0eSBTRCIsXSwgDQogICAgICAgICAgICBhZXMoeCA9IHRpbWUsIHkgPSBoZWlnaHQsIGxhYmVsID0gcHZhbHVlLCBjb2xvdXI9Y29sb3IpLCANCiAgICAgICAgICAgIHNpemUgPSA3LCBzaG93LmxlZ2VuZCA9IEZBTFNFLCBudWRnZV95ID0gLTAuMDcpICsNCiAgZ2VvbV90ZXh0KGRhdGE9a3J1c2tba3J1c2skY2F0ZWdvcnkgPT0gImNvbW11bml0eSBXTiIsXSwgDQogICAgICAgICAgICBhZXMoeCA9IHRpbWUsIHkgPSBoZWlnaHQsIGxhYmVsID0gcHZhbHVlLCBjb2xvdXI9Y29sb3IpLCANCiAgICAgICAgICAgIHNpemUgPSA3LCBzaG93LmxlZ2VuZCA9IEZBTFNFLCBudWRnZV95ID0gLTAuMDcpICsNCiAgZ2VvbV90ZXh0KGRhdGE9a3J1c2tba3J1c2skY2F0ZWdvcnkgPT0gImFiaW90aWMgU0QiLF0sDQogICAgICAgICAgICBhZXMoeCA9IHRpbWUsIHkgPSBoZWlnaHQsIGxhYmVsID0gcHZhbHVlLCBjb2xvdXI9Y29sb3IpLA0KICAgICAgICAgICAgc2l6ZSA9IDcsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgZ2VvbV90ZXh0KGRhdGE9a3J1c2tba3J1c2skY2F0ZWdvcnkgPT0gImFiaW90aWMgV04iLF0sDQogICAgICAgICAgICBhZXMoeCA9IHRpbWUsIHkgPSBoZWlnaHQsIGxhYmVsID0gcHZhbHVlLCBjb2xvdXI9Y29sb3IpLA0KICAgICAgICAgICAgc2l6ZSA9IDcsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgDQogICMgZ2VvbV9zZWdtZW50KGFlcyh4PTQsIHhlbmQ9NCwgeT0tSW5mLCB5ZW5kPUluZikpICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9c2VnbWVudF9kYXRhLCBhZXMoeCA9IHgsIHhlbmQgPSB4ZW5kLCB5ID0geSwgeWVuZCA9IHllbmQpKSArDQogIGdlb21fdGV4dChkYXRhPXNlZ21lbnRfZGF0YSwgYWVzKHggPSB4ICsgMC4yLCB5ID0gMC4yMCwgbGFiZWwgPSAiY2VsbCBzYW1wbGluZyIpLCBhbmdsZT05MCwgc2l6ZT0zKSAtPiBwbG90DQoNCnByaW50KHBsb3QpDQoNCmdnc2F2ZShwbG90ID0gcGxvdCwgZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9mb3JtYWxkZWh5ZGVfZXZvbHV0aW9uLnRpZmYiLCBkcGkgPSAzMDAsIHdpZHRoID0gMTAsIGhlaWdodCA9IDYsIGJnPSJ3aGl0ZSIpDQogIA0KYGBgDQoNCg0KIyMjIEgyTzIgZXZvbHV0aW9uDQoNCmBgYHtyIGNoZW1fcGxvdHNfSDJPMn0NCg0KY2hlbV9kYXRhX21ldGFUJGV4cGVyaW1lbnQgPC0gIm1ldGFUIg0KY2hlbV9kYXRhX21ldGFCJGV4cGVyaW1lbnQgPC0gIm1ldGFCIg0KDQpjaGVtX2RhdGEgPC0gcmJpbmQoY2hlbV9kYXRhX21ldGFULCBjaGVtX2RhdGFfbWV0YUIpDQoNCg0KDQojIyBNZXRhdHJhbnNjcmlwdG9taWNzIGRhdGENCg0KDQoNCmNoZW1fZGF0YVtjaGVtX2RhdGEkY29sb3IgPT0gIiNGOEFEMTgiICYgY2hlbV9kYXRhJGV4cGVyaW1lbnQgPT0gIm1ldGFUIixdIC0+IHRtcDINCmdyb3VwX2J5KHRtcDIsIHNhbXBsaW5nX3RpbWUpICU+JSBzdW1tYXJpc2UoSDJPMl9tZWFuPW1lYW4oSDJPMl9yYXRpb190b19pbml0aWFsKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEgyTzJfc2Q9c2QoSDJPMl9yYXRpb190b19pbml0aWFsKSkgLT4gdG1wMg0KdG1wMiRjb2xvciA8LSAiI0Y4QUQxOCINCnRtcDIkY29uZGl0aW9uIDwtICJTRCINCnRtcDIkY2F0ZWdvcnkgPC0gImJpb3RpY19TRCINCnRtcDIkZXhwZXJpbWVudCA8LSAibWV0YVQiDQoNCg0KY2hlbV9kYXRhW2NoZW1fZGF0YSRjb2xvciA9PSAiI0M0QjY5QiIgJiBjaGVtX2RhdGEkZXhwZXJpbWVudCA9PSAibWV0YVQiLF0gLT4gdG1wNA0KZ3JvdXBfYnkodG1wNCwgc2FtcGxpbmdfdGltZSkgJT4lIHN1bW1hcmlzZShIMk8yX21lYW49bWVhbihIMk8yX3JhdGlvX3RvX2luaXRpYWwpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSDJPMl9zZD1zZChIMk8yX3JhdGlvX3RvX2luaXRpYWwpKSAtPiB0bXA0DQp0bXA0JGNvbG9yIDwtICIjQzRCNjlCIg0KdG1wNCRjb25kaXRpb24gPC0gIlNEIg0KdG1wNCRjYXRlZ29yeSA8LSAiYWJpb3RpY19TRCINCnRtcDQkZXhwZXJpbWVudCA8LSAibWV0YVQiDQoNCiMjIE1ldGFib2xvbWljcyBkYXRhDQoNCg0KY2hlbV9kYXRhW2NoZW1fZGF0YSRjb2xvciA9PSAiI0Y4QUQxOCIgJiBjaGVtX2RhdGEkZXhwZXJpbWVudCA9PSAibWV0YUIiLF0gLT4gdG1wNg0KZ3JvdXBfYnkodG1wNiwgc2FtcGxpbmdfdGltZSkgJT4lIHN1bW1hcmlzZShIMk8yX21lYW49bWVhbihIMk8yX3JhdGlvX3RvX2luaXRpYWwpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSDJPMl9zZD1zZChIMk8yX3JhdGlvX3RvX2luaXRpYWwpKSAtPiB0bXA2DQp0bXA2JGNvbG9yIDwtICIjRjhBRDE4Ig0KdG1wNiRjb25kaXRpb24gPC0gIlNEIg0KdG1wNiRjYXRlZ29yeSA8LSAiYmlvdGljX1NEIg0KdG1wNiRleHBlcmltZW50IDwtICJtZXRhQiINCg0KDQpjaGVtX2RhdGFbY2hlbV9kYXRhJGNvbG9yID09ICIjQzRCNjlCIiAmIGNoZW1fZGF0YSRleHBlcmltZW50ID09ICJtZXRhQiIsXSAtPiB0bXA4DQpncm91cF9ieSh0bXA4LCBzYW1wbGluZ190aW1lKSAlPiUgc3VtbWFyaXNlKEgyTzJfbWVhbj1tZWFuKEgyTzJfcmF0aW9fdG9faW5pdGlhbCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBIMk8yX3NkPXNkKEgyTzJfcmF0aW9fdG9faW5pdGlhbCkpIC0+IHRtcDgNCnRtcDgkY29sb3IgPC0gIiNDNEI2OUIiDQp0bXA4JGNvbmRpdGlvbiA8LSAiU0QiDQp0bXA4JGNhdGVnb3J5IDwtICJhYmlvdGljX1NEIg0KdG1wOCRleHBlcmltZW50IDwtICJtZXRhQiINCg0KDQojIyBNZXJnZSBkYXRhDQoNCmxpbmVfZGF0YSA8LSByYmluZCh0bXAyLCB0bXA0LCB0bXA2LCB0bXA4KQ0Kcm0odG1wMiwgdG1wNCwgdG1wNiwgdG1wOCkNCg0KIyMgVGVzdCBkaWZmZXJlbmNlIGJldHdlZW4gdGltZSAwIGFuIHRoZSBvdGhlciB0aW1lIHBvaW50cw0KDQprcnVza2FsX2gybzIgPC0gIGMoIiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAxICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiI0Y4QUQxOCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAxICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQiRjb2xvciA9PSAiI0M0QjY5QiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYmlvdGljX1NEIiwgMyksIHJlcCgiYWJpb3RpY19TRCIsIDMpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMiAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNGOEFEMTgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMiAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19TRCIsIDMpLCByZXAoImFiaW90aWNfU0QiLCAzKSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMyAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNGOEFEMTgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhQlsoY2hlbV9kYXRhX21ldGFCJHNhbXBsaW5nX3RpbWUgPT0gMyAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImJpb3RpY19TRCIsIDMpLCByZXAoImFiaW90aWNfU0QiLCAzKSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5KGlmKGtydXNrYWwudGVzdCh4ID0gYyhjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDEgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjRjhBRDE4IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIMk8yX3JhdGlvX3RvX2luaXRpYWwiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDEgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQzRCNjlCIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIMk8yX3JhdGlvX3RvX2luaXRpYWwiXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJiaW90aWNfU0QiLCAzKSwgcmVwKCJhYmlvdGljX1NEIiwgMykpDQogICAgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAyICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0Y4QUQxOCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAyICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0M0QjY5QiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYmlvdGljX1NEIiwgMyksIHJlcCgiYWJpb3RpY19TRCIsIDMpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAzICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0Y4QUQxOCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAzICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0M0QjY5QiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYmlvdGljX1NEIiwgMyksIHJlcCgiYWJpb3RpY19TRCIsIDMpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSA1ICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0Y4QUQxOCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSA1ICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0M0QjY5QiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYmlvdGljX1NEIiwgMyksIHJlcCgiYWJpb3RpY19TRCIsIDMpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSkNCiAgICAgICAgICAgICAgICAgICAgICkNCg0Ka3J1c2thbF9kZiA8LSBkYXRhLmZyYW1lKHRpbWUgPSBjKDAsIDEsIDIsIDMsIDAsIDEsIDIsIDMsIDUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IHJlcCgwLCA5KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBleHBlcmltZW50ID0gYyhyZXAoIm1ldGFCIiwgNCksIHJlcCgibWV0YVQiLCA1KSksDQogICAgICAgICAgICAgICAgICAgICAgICAgY29uZGl0aW9uID0gcmVwKCJTRCIsIDkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGVnb3J5ID0gcmVwKCJjb21tdW5pdHkgU0QiLCA5KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IHJlcCgiI0Y4QUQxOCIsIDkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZSA9IGtydXNrYWxfaDJvMikNCg0KIyANCiMga3J1c2thbF9oMm8yX2FiaW8gPC0gYygiIiwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAxICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYWJpb3RpY19TRF9URl8xIiwgMyksIHJlcCgiYWJpb3RpY19TRF8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSkgLA0KIyAgICAgICAgICAgICAgICAgICAgICAgdHJ5KGlmKGtydXNrYWwudGVzdCh4ID0gYyhjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDIgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUJbKGNoZW1fZGF0YV9tZXRhQiRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YUIkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJhYmlvdGljX1NEX1RGXzIiLCAzKSwgcmVwKCJhYmlvdGljX1NEXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAzICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCWyhjaGVtX2RhdGFfbWV0YUIkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFCJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYWJpb3RpY19TRF9URl8zIiwgMyksIHJlcCgiYWJpb3RpY19TRF8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICAiIiwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAxICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYWJpb3RpY19TRF9URl8xIiwgMyksIHJlcCgiYWJpb3RpY19TRF8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSkgLA0KIyAgICAgICAgICAgICAgICAgICAgICAgdHJ5KGlmKGtydXNrYWwudGVzdCh4ID0gYyhjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDIgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVRbKGNoZW1fZGF0YV9tZXRhVCRzYW1wbGluZ190aW1lID09IDAgJg0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVtX2RhdGFfbWV0YVQkY29sb3IgPT0gIiNDNEI2OUIiKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSDJPMl9yYXRpb190b19pbml0aWFsIl0pLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZyA9IGMocmVwKCJhYmlvdGljX1NEX1RGXzIiLCAzKSwgcmVwKCJhYmlvdGljX1NEXzAiLCAzKSkNCiMgICAgICAgICAgICAgICAgICAgICAgIClbWyJwLnZhbHVlIl1dIDwgMC4wNSl7IioifWVsc2V7IiJ9LCBzaWxlbnQgPSBUUlVFKSwNCiMgICAgICAgICAgICAgICAgICAgICAgIHRyeShpZihrcnVza2FsLnRlc3QoeCA9IGMoY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAzICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUWyhjaGVtX2RhdGFfbWV0YVQkc2FtcGxpbmdfdGltZSA9PSAwICYNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlbV9kYXRhX21ldGFUJGNvbG9yID09ICIjQzRCNjlCIiksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgyTzJfcmF0aW9fdG9faW5pdGlhbCJdKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGcgPSBjKHJlcCgiYWJpb3RpY19TRF9URl8zIiwgMyksIHJlcCgiYWJpb3RpY19TRF8wIiwgMykpDQojICAgICAgICAgICAgICAgICAgICAgICApW1sicC52YWx1ZSJdXSA8IDAuMDUpeyIqIn1lbHNleyIifSwgc2lsZW50ID0gVFJVRSksDQojICAgICAgICAgICAgICAgICAgICAgICB0cnkoaWYoa3J1c2thbC50ZXN0KHggPSBjKGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gNSAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0M0QjY5QiIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIMk8yX3JhdGlvX3RvX2luaXRpYWwiXSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVFsoY2hlbV9kYXRhX21ldGFUJHNhbXBsaW5nX3RpbWUgPT0gMCAmDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZW1fZGF0YV9tZXRhVCRjb2xvciA9PSAiI0M0QjY5QiIpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIMk8yX3JhdGlvX3RvX2luaXRpYWwiXSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnID0gYyhyZXAoImFiaW90aWNfU0RfNSIsIDMpLCByZXAoImFiaW90aWNfU0RfMCIsIDMpKQ0KIyAgICAgICAgICAgICAgICAgICAgICAgKVtbInAudmFsdWUiXV0gPCAwLjA1KXsiKiJ9ZWxzZXsiIn0sIHNpbGVudCA9IFRSVUUpDQojICAgICAgICAgICAgICAgICAgICAgICkNCg0KIyBrcnVza2FsX2RmX2FiaW8gPC0gZGF0YS5mcmFtZSh0aW1lID0gYygwLCAxLCAyLCAzLCAwLCAxLCAyLCAzLCA1KSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IHJlcCgxLjE1LCA5KSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVyaW1lbnQgPSBjKHJlcCgibWV0YUIiLCA0KSwgcmVwKCJtZXRhVCIsIDUpKSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmRpdGlvbiA9IHJlcCgiU0QiLCA5KSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGVnb3J5ID0gcmVwKCJhYmlvdGljIFNEIiwgOSksDQojICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IHJlcCgiI0M0QjY5QiIsIDkpLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlID0ga3J1c2thbF9oMm8yX2FiaW8pDQoNCg0KIyBrcnVzayA8LSByYmluZChrcnVza2FsX2RmLCBrcnVza2FsX2RmX2FiaW8pDQprcnVzayA8LSBrcnVza2FsX2RmDQoNCg0KIyMgU2VnbWVudCBkYXRhIGZvciBzYW1wbGluZyB0aW1lDQoNCnNlZ21lbnRfZGF0YSA8LSBkYXRhLmZyYW1lKHggPSBjKDQsIDAsIDMuNSksIHhlbmQgPSBjKDQsIDAsIDMuNSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGMoLUluZiwgLUluZiwgLUluZiksIHllbmQgPSBjKEluZiwgSW5mLCBJbmYpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwZXJpbWVudCA9IGMoIm1ldGFUIiwgIm1ldGFCIiwgIm1ldGFCIikpDQogIA0KY2hlbV9kYXRhW2NoZW1fZGF0YSRjb25kaXRpb24gPT0gIlNEIixdICU+JSBnZ3Bsb3QoKSArDQogIGdlb21fcG9pbnQoYWVzKHg9c2FtcGxpbmdfdGltZSwgeT1IMk8yX3JhdGlvX3RvX2luaXRpYWwsIGNvbG9yPWNvbG9yKSkgKw0KICB5bGltKGMoLTAuMSwgMS4yKSkgKw0KICB4bGltKGMoMCwgNSkpICsNCiAgc2NhbGVfY29sb3VyX2lkZW50aXR5KCJjYXRlZ29yeSIsIGxhYmVscyA9IGMoImFiaW90aWMgU0QiLCAiY29tbXVuaXR5IFNEIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGU9ImxlZ2VuZCIpICsNCiAgc2NhbGVfZmlsbF9pZGVudGl0eSgpICsNCiAgeWxhYihsYWJlbCA9ICJSZWxhdGl2ZSBIMk8yIGV2b2x1dGlvbiIpICsNCiAgeGxhYihsYWJlbCA9ICJJbmN1YmF0aW9uIHRpbWUgKGgpIikgKw0KICAjIGZhY2V0X2dyaWQocm93cyA9IHZhcnMoZXhwZXJpbWVudCksIGNvbHMgPSB2YXJzKGNvbmRpdGlvbikpICsgIywgbnJvdz0yLCBuY29sPTINCiAgZmFjZXRfZ3JpZChyb3dzID0gdmFycyhjb25kaXRpb24pLCBjb2xzID0gdmFycyhleHBlcmltZW50KSwNCiAgICAgICAgICAgICBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGMoIm1ldGFUIiA9ICJNZXRhdHJhbnNjcmlwdG9taWNzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtZXRhQiIgPSAiTWV0YS1tZXRhYm9sb21pY3MiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0QiID0gIlNEIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldOIiA9ICJXTiIpKSkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0iI2Y0ZjRmNCIpKSArDQogIA0KICANCiAgZ2VvbV9wYXRoKGRhdGEgPSBsaW5lX2RhdGFbbGluZV9kYXRhJGNhdGVnb3J5ID09ICJiaW90aWNfU0QiLF0sIA0KICAgICAgICAgICAgYWVzKHggPSBzYW1wbGluZ190aW1lLHkgPUgyTzJfbWVhbiwgY29sb3IgPSBjb2xvciksIA0KICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyANCiAgZ2VvbV9yaWJib24oZGF0YSA9IGxpbmVfZGF0YVtsaW5lX2RhdGEkY2F0ZWdvcnkgPT0gImJpb3RpY19TRCIsXSwgDQogICAgICAgICAgICAgIGFlcyh4ID0gc2FtcGxpbmdfdGltZSwgDQogICAgICAgICAgICAgICAgICB5bWluID0gSDJPMl9tZWFuIC0gSDJPMl9zZCwNCiAgICAgICAgICAgICAgICAgIHltYXggPSBIMk8yX21lYW4gKyBIMk8yX3NkLA0KICAgICAgICAgICAgICAgICAgZmlsbCA9IGNvbG9yKSwgYWxwaGE9MC4yNSwgbGluZXdpZHRoPTAuMDUpICsNCiAgDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBsaW5lX2RhdGFbbGluZV9kYXRhJGNhdGVnb3J5ID09ICJhYmlvdGljX1NEIixdLCANCiAgICAgICAgICAgIGFlcyh4ID0gc2FtcGxpbmdfdGltZSx5ID1IMk8yX21lYW4sIGNvbG9yID0gY29sb3IpLCANCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgDQogIGdlb21fcmliYm9uKGRhdGEgPSBsaW5lX2RhdGFbbGluZV9kYXRhJGNhdGVnb3J5ID09ICJhYmlvdGljX1NEIixdLCANCiAgICAgICAgICAgICAgYWVzKHggPSBzYW1wbGluZ190aW1lLCANCiAgICAgICAgICAgICAgICAgIHltaW4gPSBIMk8yX21lYW4gLSBIMk8yX3NkLA0KICAgICAgICAgICAgICAgICAgeW1heCA9IEgyTzJfbWVhbiArIEgyTzJfc2QsDQogICAgICAgICAgICAgICAgICBmaWxsID0gY29sb3IpLCBhbHBoYT0wLjI1LCBsaW5ld2lkdGg9MC4wNSkgKw0KICANCiAgIyBwbG90IHNpZ25pZmljYW5jZSBzdGFycw0KICBnZW9tX3RleHQoZGF0YT1rcnVza1trcnVzayRjYXRlZ29yeSA9PSAiY29tbXVuaXR5IFNEIixdLCANCiAgICAgICAgICAgIGFlcyh4ID0gdGltZSwgeSA9IGhlaWdodCwgbGFiZWwgPSBwdmFsdWUsIGNvbG91cj1jb2xvciksIA0KICAgICAgICAgICAgc2l6ZSA9IDcsIHNob3cubGVnZW5kID0gRkFMU0UsIG51ZGdlX3kgPSAtMC4wNykgKw0KICBnZW9tX3RleHQoZGF0YT1rcnVza1trcnVzayRjYXRlZ29yeSA9PSAiYWJpb3RpYyBTRCIsXSwNCiAgICAgICAgICAgIGFlcyh4ID0gdGltZSwgeSA9IGhlaWdodCwgbGFiZWwgPSBwdmFsdWUsIGNvbG91cj1jb2xvciksDQogICAgICAgICAgICBzaXplID0gNywgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KDQogIA0KICAjIGdlb21fc2VnbWVudChhZXMoeD00LCB4ZW5kPTQsIHk9LUluZiwgeWVuZD1JbmYpKSArDQogIGdlb21fc2VnbWVudChkYXRhPXNlZ21lbnRfZGF0YSwgYWVzKHggPSB4LCB4ZW5kID0geGVuZCwgeSA9IHksIHllbmQgPSB5ZW5kKSkgKw0KICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtSW5mLCB4ZW5kID0gSW5mLCB5ID0gMC4yLCB5ZW5kID0gMC4yKSwgY29sb3VyID0gImRhcmtyZWQiLCBsaW5ldHlwZSA9IDIpICsNCiAgZ2VvbV90ZXh0KGRhdGE9c2VnbWVudF9kYXRhLCBhZXMoeCA9IHggKyAwLjIsIHkgPSAwLjQyLCBsYWJlbCA9ICJjZWxsIHNhbXBsaW5nIiksIGFuZ2xlPTkwLCBzaXplPTMpIC0+IHBsb3QNCg0KcHJpbnQocGxvdCkNCg0KZ2dzYXZlKHBsb3QgPSBwbG90LCBmaWxlbmFtZSA9ICIuLi9maWd1cmVzL0gyTzJfZXZvbHV0aW9uLnRpZmYiLCBkcGkgPSAzMDAsIHdpZHRoID0gMTAsIGhlaWdodCA9IDMuNiwgYmc9IndoaXRlIikNCiAgDQpgYGANCg0KDQoNCg0KIyMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcyBvbiBjb21wbGV0ZSBjb21tdW5pdHkgbWV0YXRyYW5zY3JpcHRvbWljcyBhbmQgbWV0YWJvbG9taWNzIGRhdGENCg0KIyMjIE1ldGF0cmFuc2NyaXB0b21pY3MNCg0KIyMjIyBTYW1wbGUtd2lzZSBzdGF0aXN0aWNzIChyYXcgbWV0YXRyYW5zY3JpcHRvbWljcyBjb3VudHMpDQoNCmBgYHtyIHNhbXBsZS13aXNlX3N0YXRzfQ0KDQptZXNzYWdlKCJDb21wdXRpbmcgc2FtcGxlLXdpc2Ugc3RhdGlzdGljcyBvbiByYXcgY291bnRzIikNCnNhbXBsZV9zdGF0X3ByZW5vcm0gPC0gZGF0YS5mcmFtZSgNCiAgbWVhbiA9IGFwcGx5KGNvdW50c190YWJsZSwgMiwgbWVhbiwgbmEucm0gPSBUUlVFKSwNCiAgc2QgPSBhcHBseShjb3VudHNfdGFibGUsIDIsIHNkLCBuYS5ybSA9IFRSVUUpLA0KICBpcXIgPSBhcHBseShjb3VudHNfdGFibGUsIDIsIElRUiwgbmEucm0gPSBUUlVFKSwNCiAgUTEgPSBhcHBseShjb3VudHNfdGFibGUsIDIsIHF1YW50aWxlLCBwID0gMC4yNSwgbmEucm0gPSBUUlVFKSwNCiAgbWVkaWFuID0gYXBwbHkoY291bnRzX3RhYmxlLCAyLCBtZWRpYW4sIG5hLnJtID0gVFJVRSksDQogIFEzID0gYXBwbHkoY291bnRzX3RhYmxlLCAyLCBxdWFudGlsZSwgcCA9IDAuNzUsIG5hLnJtID0gVFJVRSksDQogIG1heCA9IGFwcGx5KGNvdW50c190YWJsZSwgMiwgbWF4LCBuYS5ybSA9IFRSVUUpLA0KICBudWxsID0gYXBwbHkoY291bnRzX3RhYmxlID09IDAsIDIsIHN1bSwgbmEucm0gPSBUUlVFKQ0KKQ0KDQprYWJsZShzYW1wbGVfc3RhdF9wcmVub3JtWzA6NiwgXSwgY2FwdGlvbiA9ICJTYW1wbGUtd2lzZSBzdGF0aXN0aWNzIGJlZm9yZSBub3JtYWxpc2F0aW9uIikNCmBgYA0KDQojIyMjIEdlbmUtd2lzZSBzdGF0aXN0aWNzIChyYXcgbWV0YXRyYW5zY3JpcHRvbWljcyBjb3VudHMpDQoNCmBgYHtyIGdlbmUtd2lzZV9zdGF0c30NCg0KbWVzc2FnZSgiQ29tcHV0aW5nIGdlbmUtd2lzZSBzdGF0aXN0aWNzIG9uIHJhdyBjb3VudHMiKQ0KZ2VuZV9zdGF0X3ByZW5vcm0gPC0gZGF0YS5mcmFtZSgNCiAgbWVhbiA9IGFwcGx5KGNvdW50c190YWJsZSwgMSwgbWVhbiwgbmEucm0gPSBUUlVFKSwNCiAgc2QgPSBhcHBseShjb3VudHNfdGFibGUsIDEsIHNkLCBuYS5ybSA9IFRSVUUpLA0KICBpcXIgPSBhcHBseShjb3VudHNfdGFibGUsIDEsIElRUiwgbmEucm0gPSBUUlVFKSwNCiAgUTEgPSBhcHBseShjb3VudHNfdGFibGUsIDEsIHF1YW50aWxlLCBwID0gMC4yNSwgbmEucm0gPSBUUlVFKSwNCiAgbWVkaWFuID0gYXBwbHkoY291bnRzX3RhYmxlLCAxLCBtZWRpYW4sIG5hLnJtID0gVFJVRSksDQogIFEzID0gYXBwbHkoY291bnRzX3RhYmxlLCAxLCBxdWFudGlsZSwgcCA9IDAuNzUsIG5hLnJtID0gVFJVRSksDQogIG1heCA9IGFwcGx5KGNvdW50c190YWJsZSwgMSwgbWF4LCBuYS5ybSA9IFRSVUUpLA0KICBudWxsID0gYXBwbHkoY291bnRzX3RhYmxlID09IDAsIDEsIHN1bSwgbmEucm0gPSBUUlVFKQ0KKQ0KDQoja2FibGUoZ2VuZV9zdGF0X3ByZW5vcm1bMTAwOjEwOSwgXSwgY2FwdGlvbiA9ICJHZW5lLXdpc2Ugc3RhdGlzdGljcyBiZWZvcmUgbm9ybWFsaXNhdGlvbiIpDQpgYGANCg0KIyMjIyBaZXJvZXMgZmlsdGVyaW5nIGFuZCBzbW9vdGhpbmcgaW5zcGlyZWQgYnkgTVRYbW9kZWwgYXJ0aWNsZSBbKFpoYW5nIGV0IGFsLiAyMDIxKV0oaHR0cHM6Ly9kb2kub3JnLzEwLjEwOTMvYmlvaW5mb3JtYXRpY3MvYnRhYjMyNykNCg0KYGBge3IgbGlzdHN9DQpzcGVjaWVzIDwtIHVubGlzdCh1bmlxdWUoYW5ub3RhdGlvbl90YWJsZVssIk9yZ2FuaXNtIl0pKQ0Kc2FtcGxlcyA8LSByb3cubmFtZXMobWV0YWRhdGFfdGFibGUpDQpgYGANCg0KR2VuZSB3aXRoIDAgY291bnRzIGluIG1vcmUgdGhhbiA3MCUgb2Ygc2FtcGxlcyBhcmUgZGVlbWVkIHVuZXhwcmVzc2VkIGFuZCBhcmUgcmVtb3ZlZCBmcm9tIHRoZSBkYXRhc2V0LiAgDQoNCmBgYHtyIE1UWF96ZXJvX2ZpbHRlcmluZywgcmVzdWx0cz0nYXNpcyd9DQptZXNzYWdlKCJGaWx0ZXJpbmcgdW5kZXRlY3RlZCBnZW5lcyIpDQp1bmRldGVjdGVkX2dlbmVzIDwtIGdlbmVfc3RhdF9wcmVub3JtJG51bGwgPj0gbmNvbChjb3VudHNfdGFibGUpICogMC43MA0KcHJpbnQocGFzdGUwKCJVbmRldGVjdGVkIGdlbmVzIChudWxsIGluID49IDcwJSBzYW1wbGVzKTogIiwgc3VtKHVuZGV0ZWN0ZWRfZ2VuZXMpKSkNCg0Ka2VwdF9nZW5lcyA8LSAhdW5kZXRlY3RlZF9nZW5lcw0KcHJpbnQocGFzdGUwKCJLZXB0IGdlbmVzOiAiLCBzdW0oa2VwdF9nZW5lcykpKQ0KDQojIyBHZW5lcyBhZnRlciBmaWx0ZXJpbmcNCmNvdW50c19maWx0ZXJlZCA8LSBjb3VudHNfdGFibGVba2VwdF9nZW5lcywgXQ0KYW5ub3RhdGlvbl90YWJsZSA8LSBhbm5vdGF0aW9uX2FsbFtyb3duYW1lcyhjb3VudHNfZmlsdGVyZWQpLF0gI3Jvdy5uYW1lcygpDQoNCiMjIFNwZWNpZXMgYWJ1bmRhbmNlIChzdW0gb2YgYWxsIGNvdW50cykNCnRvdGFsc19kZiA8LSBkYXRhLmZyYW1lKCkNCmZvciAoc3BlIGluIHNwZWNpZXMpIHsNCiAgc3BlX2dlbmVpZCA8LSBhbm5vdGF0aW9uX3RhYmxlJE9yZ2FuaXNtID09IHNwZQ0KICBmb3IgKHNhbXAgaW4gc2FtcGxlcykgew0KICAgIHRvdGFsc19kZltzcGUsIHNhbXBdIDwtIHN1bShjb3VudHNfZmlsdGVyZWRbc3BlX2dlbmVpZCwgc2FtcF0sIG5hLnJtPVRSVUUpDQogIH0NCn0NCg0KYGBgDQoNCmBgYHtyIG5vX3N0YW5kYXJkaXNhdGlvbn0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIHJlbW92ZSBzdGFuZGFyZGlzYXRpb24/Pz8gIyMjIyMjIyMjIyMjDQpjb3VudHNfc3RhbmRhcmQgPC0gY291bnRzX2ZpbHRlcmVkDQp0YWJsZV9nZW5lX2V4cHIgPC0gY291bnRzX3RhYmxlDQp0YWJsZV9nZW5lX2V4cHIkZGV0ZWN0ZWQgPC0gIk5vIg0KdGFibGVfZ2VuZV9leHByW2tlcHRfZ2VuZXMsICJkZXRlY3RlZCJdIDwtICJ5ZXMiDQp0YWJsZV9nZW5lX2V4cHIgPC0gcm93bmFtZXNfdG9fY29sdW1uKHRhYmxlX2dlbmVfZXhwcikNCnRhYmxlX2dlbmVfZXhwciA8LSBsZWZ0X2pvaW4odGFibGVfZ2VuZV9leHByLCByb3duYW1lc190b19jb2x1bW4oYW5ub3RhdGlvbl90YWJsZV9sb25nKVssYygicm93bmFtZSIsICJsb2N1c190YWciLCAidHJhbnNjcmlwdElkIildKQ0KIyB3cml0ZV9kZWxpbSh0YWJsZV9nZW5lX2V4cHIsIGZpbGUgPSAiLi4vcmVzdWx0cy90YWJsZV9vZl9rZXB0X2V4cHJlc3NlZF9nZW5lcy50c3YiLCBkZWxpbSA9ICJcdCIsICkNCmBgYA0KDQpgYGB7ciB6ZXJvZXNfc21vb3RoaW5nX21ldGF0cmFuc2NyaXB0b21pY3N9DQojIyByZW1haW5pbmcgemVyb2VzIHNtb290aGluZyAoYXMgaW4gWmhhbmcgZXQgYWwuIDIwMjEpDQoNCm1pbl92YWwgPC0gYXBwbHkoY291bnRzX3N0YW5kYXJkLCAxLCBmdW5jdGlvbih4KSAobWluKHhbeD4wXSkvMikpDQoNCg0KZm9yIChnZW5lIGluIHJvdy5uYW1lcyhjb3VudHNfc3RhbmRhcmQpKSB7DQogIGNvdW50c19zdGFuZGFyZFtnZW5lLF1bY291bnRzX3N0YW5kYXJkW2dlbmUsXSA9PSAwXSA8LSBtaW5fdmFsW2dlbmVdDQp9DQoNCmBgYA0KDQpgYGB7ciBzYW1wbGVfd2lzZV9zdGF0c19maWx0ZXJlZH0NCm1lc3NhZ2UoIkNvbXB1dGluZyBzYW1wbGUtd2lzZSBzdGF0aXN0aWNzIG9uIGZpbHRlcmVkIGNvdW50cyIpDQpzYW1wbGVfc3RhdF9maWx0IDwtIGRhdGEuZnJhbWUoDQogIG1lYW4gPSBhcHBseShjb3VudHNfc3RhbmRhcmQsIDIsIG1lYW4sIG5hLnJtID0gVFJVRSksDQogIHNkID0gYXBwbHkoY291bnRzX3N0YW5kYXJkLCAyLCBzZCwgbmEucm0gPSBUUlVFKSwNCiAgaXFyID0gYXBwbHkoY291bnRzX3N0YW5kYXJkLCAyLCBJUVIsIG5hLnJtID0gVFJVRSksDQogIFExID0gYXBwbHkoY291bnRzX3N0YW5kYXJkLCAyLCBxdWFudGlsZSwgcCA9IDAuMjUsIG5hLnJtID0gVFJVRSksDQogIG1lZGlhbiA9IGFwcGx5KGNvdW50c19zdGFuZGFyZCwgMiwgbWVkaWFuLCBuYS5ybSA9IFRSVUUpLA0KICBRMyA9IGFwcGx5KGNvdW50c19zdGFuZGFyZCwgMiwgcXVhbnRpbGUsIHAgPSAwLjc1LCBuYS5ybSA9IFRSVUUpLA0KICBtYXggPSBhcHBseShjb3VudHNfc3RhbmRhcmQsIDIsIG1heCwgbmEucm0gPSBUUlVFKSwNCiAgbnVsbCA9IGFwcGx5KGNvdW50c19zdGFuZGFyZCA9PSAwLCAyLCBzdW0sIG5hLnJtID0gVFJVRSkNCikNCg0Ka2FibGUoc2FtcGxlX3N0YXRfZmlsdFswOjYsIF0sIGNhcHRpb24gPSAiU2FtcGxlLXdpc2Ugc3RhdGlzdGljcyBhZnRlciBmaWx0ZXJpbmciKQ0KYGBgDQoNCiMjIyMgQ0xSIChDZW50ZXJlZCBMb2cgcmF0aW8pIHRyYW5zZm9ybWF0aW9uIG9mIHdob2xlIGNvbW11bml0eSBtZXRhdHJhbnNjcmlwdG9taWNzIGNvdW50cw0KDQpgYGB7ciBDTFJfdHJhbnNmb3JtYXRpb259DQoNCmNvdW50c19jbHIgPC0gY291bnRzX3N0YW5kYXJkDQoNCmZvciAoc2FtcCBpbiBzYW1wbGVzKSB7DQogIGNvdW50c19jbHJbLHNhbXBdIDwtIGNscihjb3VudHNfc3RhbmRhcmRbLHNhbXBdKQ0KfQ0KYGBgDQoNCmBgYHtyIHNhbXBsZV93aXNlX3N0YXRzX2Nscn0NCm1lc3NhZ2UoIkNvbXB1dGluZyBzYW1wbGUtd2lzZSBzdGF0aXN0aWNzIG9uIGZpbHRlcmVkIGNvdW50cyIpDQpzYW1wbGVfc3RhdF9jbHIgPC0gZGF0YS5mcmFtZSgNCiAgbWVhbiA9IGFwcGx5KGNvdW50c19jbHIsIDIsIG1lYW4sIG5hLnJtID0gVFJVRSksDQogIHNkID0gYXBwbHkoY291bnRzX2NsciwgMiwgc2QsIG5hLnJtID0gVFJVRSksDQogIGlxciA9IGFwcGx5KGNvdW50c19jbHIsIDIsIElRUiwgbmEucm0gPSBUUlVFKSwNCiAgUTEgPSBhcHBseShjb3VudHNfY2xyLCAyLCBxdWFudGlsZSwgcCA9IDAuMjUsIG5hLnJtID0gVFJVRSksDQogIG1lZGlhbiA9IGFwcGx5KGNvdW50c19jbHIsIDIsIG1lZGlhbiwgbmEucm0gPSBUUlVFKSwNCiAgUTMgPSBhcHBseShjb3VudHNfY2xyLCAyLCBxdWFudGlsZSwgcCA9IDAuNzUsIG5hLnJtID0gVFJVRSksDQogIG1heCA9IGFwcGx5KGNvdW50c19jbHIsIDIsIG1heCwgbmEucm0gPSBUUlVFKSwNCiAgbnVsbCA9IGFwcGx5KGNvdW50c19jbHIgPT0gMCwgMiwgc3VtLCBuYS5ybSA9IFRSVUUpDQopDQoNCmthYmxlKHNhbXBsZV9zdGF0X2NsclswOjYsIF0sIGNhcHRpb24gPSAiU2FtcGxlLXdpc2Ugc3RhdGlzdGljcyBhZnRlciBDTFIgdHJhbnNmb3JtYXRpb24iKQ0KYGBgDQoNCmBgYHtyIGdlbmVfc3RhdHNfbm9ybX0NCiMjIEdlbmUtd2lzZSBzdGF0aXN0aWNzIGFmdGVyIG5vcm1hbGlzYXRpb24NCm1lc3NhZ2UoIkNvbXB1dGluZyBnZW5lLXdpc2Ugc3RhdGlzdGljcyBvbiBsb2ctdHJhbnNmb3JtZWQgYW5kIG5vcm1hbGlzZWQgY291bnRzIikNCmdlbmVfc3RhdF9ub3JtIDwtIGRhdGEuZnJhbWUobWVhbiA9IGFwcGx5KGNvdW50c19jbHIsIDEsIG1lYW4sIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgPSBhcHBseShjb3VudHNfY2xyLCAxLCB2YXIsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZCA9IGFwcGx5KGNvdW50c19jbHIsIDEsIHNkLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXFyID0gYXBwbHkoY291bnRzX2NsciwgMSwgSVFSLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluID0gYXBwbHkoY291bnRzX2NsciwgMSwgbWluLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkID0gYXBwbHkoY291bnRzX2NsciwgMSwgbWVkaWFuLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4ID0gYXBwbHkoY291bnRzX2NsciwgMSwgbWF4LCBuYS5ybT1UUlVFKSkNCg0KIyBBam91dCBkdSBjb2VmZmljaWVudCBkZSB2YXJpYXRpb24NCmdlbmVfc3RhdF9ub3JtJGNvZWZfdmFyIDwtIChnZW5lX3N0YXRfbm9ybSRzZCAvIGdlbmVfc3RhdF9ub3JtJG1lYW4pDQoNCg0KYGBgDQoNCiMjIyMgTWV0YXRyYW5zY3JpcHRvbWljcyBjb3VudHMgZGlzdHJpYnV0aW9uDQoNCmBgYHtyIGhpc3RfcmF3LCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQ0KcGFyKG1mcm93PWMoMSwxKSkNCmhpc3QodW5saXN0KGNvdW50c190YWJsZSksDQogICAgIGJyZWFrcyA9IDIwMCwNCiAgICAgY2V4LmF4aXMgPSAwLjcsDQogICAgIGxhcyA9IDEsDQogICAgIGNvbCA9ICJza3libHVlIiwNCiAgICAgeGxhYiA9ICJyYXcgY291bnRzIiwNCiAgICAgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgcmF3IGNvdW50cyIpDQpgYGANCg0KYGBge3IgaGlzdF9jbHIsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9DQpwYXIobWZyb3c9YygxLDEpKQ0KaGlzdCh1bmxpc3QoY291bnRzX2NsciksDQogICAgIGJyZWFrcyA9IDIwMCwNCiAgICAgY2V4LmF4aXMgPSAwLjcsDQogICAgIGxhcyA9IDEsDQogICAgIGNvbCA9ICJza3libHVlIiwNCiAgICAgeGxhYiA9ICJjbHItdHJhbnNmb3JtZWQgY291bnRzIiwNCiAgICAgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgY2xyLXRyYW5zZm9ybWVkIGNvdW50cyIpDQpgYGANCg0KVGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgd2hvbGUgY29tbXVuaXR5IG1ldGF0cmFuc2NyaXB0b21pY3MgY291bnRzIHNlZW1zIGNsb3NlIHRvIG5vcm1hbC4NCg0KYGBge3IgYm94X3Bsb3RfcmF3LCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQ0KIyBSYXcgZGF0YQ0KYm94cGxvdChjb3VudHNfdGFibGUsDQogICAgICAgIG1haW4gPSAiUmF3IGV4cHJlc3Npb24iLA0KICAgICAgICBob3Jpem9udGFsID0gVFJVRSwNCiAgICAgICAgY29sID0gbWV0YWRhdGFfdGFibGUkY29sb3IsDQogICAgICAgIGNleCA9IDAuNSwNCiAgICAgICAgY2V4LmF4aXMgPSAwLjgsDQogICAgICAgIGxhcyA9IDEpDQpgYGANCg0KYGBge3IgYm94X3Bsb3RfY2xyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQ0KYm94cGxvdChjb3VudHNfY2xyLA0KICAgICAgICBtYWluID0gImNsci10cmFuc2Zvcm1lZCBleHByZXNzaW9uIiwNCiAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUsDQogICAgICAgIGNvbCA9IG1ldGFkYXRhX3RhYmxlJGNvbG9yLA0KICAgICAgICBjZXggPSAwLjUsDQogICAgICAgIGNleC5heGlzID0gMC44LA0KICAgICAgICBsYXMgPSAxKQ0KYGBgDQoNCg0KVGhlIENMUiB0cmFuc2Zvcm1hdGlvbiBjZW50cmVkIG91ciBkYXRhLg0KDQoNCiMjIyMgQ29tbXVuaXR5IG1ldGF0cmFuc2NyaXB0b21pY3MgY291bnRzIHJlcGFydGl0aW9uIGJ5IHNwZWNpZXMNCg0KYGBge3Igc3BlY2llc19yZXBhcnRpdGlvbl90YWJsZX0NCnRvdGFsc19kZiRzcGVjaWVzIDwtIHJvdy5uYW1lcygodG90YWxzX2RmKSkNCnRvdGFsc19kZiAlPiUNCiAgICBwaXZvdF9sb25nZXIoIXNwZWNpZXMsIA0KICAgICAgICAgICAgICAgIG5hbWVzX3RvPWMoInNhbXBsZSIpLA0KICAgICAgICAgICAgICAgIHZhbHVlc190bz0idG90YWxfY291bnRzIikgJT4lDQogIG11dGF0ZShzYW1wbGUgPSBjYXNlX3doZW4oc2FtcGxlID09ICJTRF9URl8xIiB+ICJTRF9URl8xIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGUgPT0gIlNEX1RGXzIiIH4gIlNEX1RGXzIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZSA9PSAiU0RfVEZfMyIgfiAiU0RfVEZfMyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlID09ICJXTl9URl8xIiB+ICJXTl9URl8xIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGUgPT0gIldOX1RGXzIiIH4gIldOX1RGXzIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZSA9PSAiV05fVEZfMyIgfiAiV05fVEZfMyIpKSAtPiB0b3RhbHNfZGYNCmBgYA0KDQpgYGB7ciBzcGVjaWVzX3JlcGFydGl0aW9uX3Bsb3QsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9DQoNCg0KZ2dwbG90KGRhdGE9dG90YWxzX2RmLCBtYXBwaW5nPWFlcyh4PXNhbXBsZSwgeT10b3RhbF9jb3VudHMsIGZpbGw9c3BlY2llcykpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIA0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlB1T3IiKSArDQogIGxhYnMoeSA9ICJQZXJjZW50YWdlIG9mIHRvdGFsIGNvdW50cyIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGFzX2Z1bmN0aW9uKH4gMTAwICogLikpICsgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9IGMoIlNEX1RGXzEiID0gImRhcmtvcmFuZ2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRF9URl8yIiA9ICJkYXJrb3JhbmdlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0RfVEZfMyIgPSAiZGFya29yYW5nZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldOX1RGXzEiID0gImRhcmtjeWFuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV05fVEZfMiIgPSAiZGFya2N5YW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXTl9URl8zIiA9ICJkYXJrY3lhbiIpKSkgKyANCiAgZ2d0aXRsZSgiVG90YWwgbWV0YXRyYW5zY3JpcHRvbWljcyBjb3VudHMgcGVyIHNwZWNpZXMiKSAtPiBwIA0KDQpwcmludChwKQ0KDQpnZ3NhdmUoIi4uL2ZpZ3VyZXMvRmlndXJlX1MzX2NvdW50c19yZXBhcnRpdGlvbi5wbmciLCBwLCBkcGkgPSAzMDApDQpnZ3NhdmUoIi4uL2ZpZ3VyZXMvRmlndXJlX1MzX2NvdW50c19yZXBhcnRpdGlvbi50aWZmIiwgcCwgaGVpZ2h0ID0gNywgd2lkdGggPSA3LCBkcGkgPSAzMDApDQpgYGANCg0KQXMgcHJldmlvdXNseSBub3RlZCwgKkRpb3N6ZWdpYSBodW5nYXJpY2EqIGNvdW50cyBhcmUgbGFyZ2VseSBkb21pbmFudCBpbiBvdXIgZGF0YS4gKlBzZXVkb21vbmFzIGdyYW1pbmlzKiBhc3NvY2lhdGVkIGNvdW50cyBhcmUgdmVyeSByYXJlLg0KDQojIyMjIyAqRC4gaHVuZ2FyaWNhKiBmaWx0ZXJlZCBjb3VudHMgcmVwYXJ0aXRpb24gYnkgbnVjbGV1cyBvciBtaXRvY2hvbmRyaWFsIG9yaWdpbg0KDQpgYGB7ciBkaW9zemVnaWFfZ2Vub21lX29yaWdpbl90cmFuc2NyaXB0cywgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9N30NCg0Kb3JnYW5lbGxlX2RmIDwtIGRhdGEuZnJhbWUoKQ0KDQptaXRvX2dlbmVpZCA8LSBhbm5vdGF0aW9uX3RhYmxlJENociA9PSAiRGlvc3plZ2lhX2h1bmdhcmljYV9QREQtMjRiLTJfY29udGlnXzM1Ig0KbnVjbF9nZW5laWQgPC0gKGFubm90YXRpb25fdGFibGUkT3JnYW5pc20gPT0gIkQuaHVuZ2FyaWNhIiAmIGFubm90YXRpb25fdGFibGUkQ2hyICE9ICJEaW9zemVnaWFfaHVuZ2FyaWNhX1BERC0yNGItMl9jb250aWdfMzUiKQ0KDQpmb3IgKHNhbXAgaW4gc2FtcGxlcykgew0KICAgIG9yZ2FuZWxsZV9kZlsibWl0b2Nob25kcmlhIiwgc2FtcF0gPC0gc3VtKGNvdW50c19maWx0ZXJlZFttaXRvX2dlbmVpZCwgc2FtcF0sIG5hLnJtPVRSVUUpDQogICAgb3JnYW5lbGxlX2RmWyJudWNsZXVzIiwgc2FtcF0gPC0gc3VtKGNvdW50c19maWx0ZXJlZFtudWNsX2dlbmVpZCwgc2FtcF0sIG5hLnJtPVRSVUUpDQp9DQoNCm9yZ2FuZWxsZV9kZiRvcmdhbmVsbGUgPC0gcm93Lm5hbWVzKChvcmdhbmVsbGVfZGYpKQ0Kb3JnYW5lbGxlX2RmICU+JQ0KICAgIHBpdm90X2xvbmdlcighb3JnYW5lbGxlLCANCiAgICAgICAgICAgICAgICBuYW1lc190bz1jKCJzYW1wbGUiKSwNCiAgICAgICAgICAgICAgICB2YWx1ZXNfdG89InRvdGFsX2NvdW50cyIpICU+JQ0KICBtdXRhdGUoc2FtcGxlID0gY2FzZV93aGVuKHNhbXBsZSA9PSAiU0RfVEZfMSIgfiAiU0RfVEZfMSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlID09ICJTRF9URl8yIiB+ICJTRF9URl8yIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGUgPT0gIlNEX1RGXzMiIH4gIlNEX1RGXzMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZSA9PSAiV05fVEZfMSIgfiAiV05fVEZfMSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlID09ICJXTl9URl8yIiB+ICJXTl9URl8yIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGUgPT0gIldOX1RGXzMiIH4gIldOX1RGXzMiKSkgLT4gb3JnYW5lbGxlX2RmDQoNCmdncGxvdChkYXRhPW9yZ2FuZWxsZV9kZiwgbWFwcGluZz1hZXMoeD1zYW1wbGUsIHk9dG90YWxfY291bnRzLCBmaWxsPW9yZ2FuZWxsZSkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIA0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlB1T3IiKSArDQogIGxhYnMoeSA9ICJQZXJjZW50YWdlIG9mIHRvdGFsIGNvdW50cyIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGFzX2Z1bmN0aW9uKH4gMTAwICogLikpICsgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9IGMoIlNEX1RGXzEiID0gImRhcmtvcmFuZ2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRF9URl8yIiA9ICJkYXJrb3JhbmdlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0RfVEZfMyIgPSAiZGFya29yYW5nZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldOX1RGXzEiID0gImRhcmtjeWFuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV05fVEZfMiIgPSAiZGFya2N5YW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXTl9URl8zIiA9ICJkYXJrY3lhbiIpKSkgKyANCiAgZ2d0aXRsZSgiVG90YWwgdHJhbnNjcmlwdCBjb3VudHMgcGVyIEQuIGh1bmdhcmljYSBjb21wYXJ0bWVudCIpIC0+IHAgDQoNCnByaW50KHApDQoNCmdnc2F2ZSgiLi4vZmlndXJlcy9EaW9odV9jb3VudHNfcmVwYXJ0aXRpb24ucG5nIiwgcCwgZHBpID0gMzAwKQ0KZ2dzYXZlKCIuLi9maWd1cmVzL0Rpb2h1X2NvdW50c19yZXBhcnRpdGlvbi50aWZmIiwgcCwgaGVpZ2h0ID0gNywgd2lkdGggPSA3LCBkcGkgPSAzMDApDQoNCmBgYA0KDQoNCioqQW1vbmcgKkRpb3N6ZWdpYSBodW5nYXJpY2EqIGNvdW50cywgYSBsYXJnZSBwb3J0aW9uIGNvbWUgZnJvbSB0cmFuc2NyaXB0cyBwcm9kdWNlZCBpbiB0aGUgbWl0b2Nob25kcmlhLCBlc3BlY2lhbGx5IGluIFNEIGNvbmRpdGlvbnMuKioNCg0KDQojIyMgTWV0YWJvbG9taWNzDQoNCiMjIyMgTWV0YWJvbGl0ZS13aXNlIHN0YXRpc3RpY3MgKHJhdyBkYXRhKQ0KDQpgYGB7ciBtZXRhYm9saXRlLXdpc2Vfc3RhdHN9DQoNCiMgbWVzc2FnZSgiQ29tcHV0aW5nIG1ldGFib2xpdGUtd2lzZSBzdGF0aXN0aWNzIG9uIHJhdyBjb3VudHMiKQ0KDQptZXRhYm9saXRlX3N0YXRfcHJlbm9ybSA8LSBkYXRhLmZyYW1lKA0KICBtZWFuID0gYXBwbHkobWV0YWJvbG9taWNzX2FsbF90aW1lc19kZiwgMSwgbWVhbiwgbmEucm0gPSBUUlVFKSwNCiAgc2QgPSBhcHBseShtZXRhYm9sb21pY3NfYWxsX3RpbWVzX2RmLCAxLCBzZCwgbmEucm0gPSBUUlVFKSwNCiAgaXFyID0gYXBwbHkobWV0YWJvbG9taWNzX2FsbF90aW1lc19kZiwgMSwgSVFSLCBuYS5ybSA9IFRSVUUpLA0KICBRMSA9IGFwcGx5KG1ldGFib2xvbWljc19hbGxfdGltZXNfZGYsIDEsIHF1YW50aWxlLCBwID0gMC4yNSwgbmEucm0gPSBUUlVFKSwNCiAgbWVkaWFuID0gYXBwbHkobWV0YWJvbG9taWNzX2FsbF90aW1lc19kZiwgMSwgbWVkaWFuLCBuYS5ybSA9IFRSVUUpLA0KICBRMyA9IGFwcGx5KG1ldGFib2xvbWljc19hbGxfdGltZXNfZGYsIDEsIHF1YW50aWxlLCBwID0gMC43NSwgbmEucm0gPSBUUlVFKSwNCiAgbWF4ID0gYXBwbHkobWV0YWJvbG9taWNzX2FsbF90aW1lc19kZiwgMSwgbWF4LCBuYS5ybSA9IFRSVUUpLA0KICBudWxsID0gYXBwbHkobWV0YWJvbG9taWNzX2FsbF90aW1lc19kZiA9PSAwLCAxLCBzdW0sIG5hLnJtID0gVFJVRSkNCikNCg0Ka2FibGUobWV0YWJvbGl0ZV9zdGF0X3ByZW5vcm1bMTAwOjEwOSwgXSwgY2FwdGlvbiA9ICJHZW5lLXdpc2Ugc3RhdGlzdGljcyBiZWZvcmUgbm9ybWFsaXNhdGlvbiIpDQpgYGANCg0KIyMjIyBaZXJvIGZpbHRlcmluZyBhbmQgc21vb3RoaW5nIG1ldGFib2xvbWljcw0KDQpNZXRhYm9saXRlcyB3aXRoIDAgY291bnRzIGluIG1vcmUgdGhhbiA3MCUgb2Ygc2FtcGxlcyBhcmUgZGVlbWVkIHVuZXhwcmVzc2VkIGFuZCBhcmUgcmVtb3ZlZCBmcm9tIHRoZSBkYXRhc2V0LiAgDQoNCg0KDQpgYGB7ciBNZXRhYm9sb21pY3NfYWxsX3RpbWVzX3plcm9fZmlsdGVyaW5nLCByZXN1bHRzPSdhc2lzJ30NCg0KbWVzc2FnZSgiRmlsdGVyaW5nIHVuZGV0ZWN0ZWQgbWV0YWJvbGl0ZXMiKQ0KdW5kZXRlY3RlZF9tZXRhYm9saXRlcyA8LSBtZXRhYm9saXRlX3N0YXRfcHJlbm9ybSRudWxsID49IG5jb2wobWV0YWJvbG9taWNzX2FsbF90aW1lc19kZikgKiAwLjcwDQpwcmludChwYXN0ZTAoInVuZGV0ZWN0ZWRfbWV0YWJvbGl0ZXMgKG51bGwgaW4gPj0gNzAlIHNhbXBsZXMpOiAiLCBzdW0odW5kZXRlY3RlZF9tZXRhYm9saXRlcykpKQ0KDQprZXB0X21ldGFib2xpdGVzIDwtICF1bmRldGVjdGVkX21ldGFib2xpdGVzDQpwcmludChwYXN0ZTAoIktlcHQgbWV0YWJvbGl0ZXM6ICIsIHN1bShrZXB0X21ldGFib2xpdGVzKSkpDQoNCiMjIG1ldGFib2xpdGVzIGFmdGVyIGZpbHRlcmluZw0KbWV0YWJvbG9taWNzX2FsbF90aW1lc19maWx0ZXJlZCA8LSBtZXRhYm9sb21pY3NfYWxsX3RpbWVzX2RmW2tlcHRfbWV0YWJvbGl0ZXMsIF0NCg0KYGBgDQoNCg0KYGBge3IgTWV0YWJvbG9taWNzX2FsbF90aW1lc196ZXJvZXNfc21vb3RoaW5nfQ0KIyMgcmVtYWluaW5nIHplcm9lcyBzbW9vdGhpbmcgKGFzIGluIFpoYW5nIGV0IGFsLiAyMDIxKQ0KDQptaW5fdmFsIDwtIGFwcGx5KG1ldGFib2xvbWljc19hbGxfdGltZXNfZmlsdGVyZWQsIDEsIGZ1bmN0aW9uKHgpIChtaW4oeFt4PjBdKS8yKSkNCg0KDQpmb3IgKG1ldGFib2xpdGUgaW4gcm93Lm5hbWVzKG1ldGFib2xvbWljc19hbGxfdGltZXNfZmlsdGVyZWQpKSB7DQogIG1ldGFib2xvbWljc19hbGxfdGltZXNfZmlsdGVyZWRbbWV0YWJvbGl0ZSxdW21ldGFib2xvbWljc19hbGxfdGltZXNfZmlsdGVyZWRbbWV0YWJvbGl0ZSxdID09IDBdIDwtIG1pbl92YWxbbWV0YWJvbGl0ZV0NCn0NCg0KYGBgDQoNCiMjIyMgQ0xSIHRyYW5zZm9ybWF0aW9uIG1ldGFib2xvbWljcw0KDQpgYGB7ciBtZXRhYm9sb21pY3NfYWxsX3RpbWVzX0NMUn0NCm1ldGFib2xvbWljc19hbGxfdGltZXNfY2xyIDwtIG1ldGFib2xvbWljc19hbGxfdGltZXNfZmlsdGVyZWQNCg0KZm9yIChzYW1wIGluIG5hbWVzKG1ldGFib2xvbWljc19hbGxfdGltZXNfZmlsdGVyZWQgKSl7DQogIG1ldGFib2xvbWljc19hbGxfdGltZXNfY2xyWyxzYW1wXSA8LSBhcy52ZWN0b3IoY2xyKG1ldGFib2xvbWljc19hbGxfdGltZXNfZmlsdGVyZWRbLHNhbXBdKSkNCn0NCmBgYA0KDQoNCg0KIyMjIyBNZXRhYm9sb21pY3MgZGF0YSByZXBhcnRpdGlvbg0KDQpgYGB7ciBoaXN0X21ldGFCX3JhdywgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9N30NCnBhcihtZnJvdz1jKDEsMSkpDQpoaXN0KHVubGlzdChtZXRhYm9sb21pY3NfYWxsX3RpbWVzX2RmKSwNCiAgICAgYnJlYWtzID0gMjAwLA0KICAgICBjZXguYXhpcyA9IDAuNywNCiAgICAgbGFzID0gMSwNCiAgICAgY29sID0gInNreWJsdWUiLA0KICAgICB4bGFiID0gInJhdyBtZXRhYm9sb21pY3MgZGF0YSIsDQogICAgIG1haW4gPSAiRGlzdHJpYnV0aW9uIG9mIHJhdyBtZXRhYm9sb21pY3MgZGF0YSIpDQpgYGANCg0KDQoNCmBgYHtyIGhpc3RfbWV0YUJfYWxsX3RpbWVzX2NsciwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9N30NCnBhcihtZnJvdz1jKDEsMSkpDQpoaXN0KHVubGlzdChtZXRhYm9sb21pY3NfYWxsX3RpbWVzX2NsciksDQogICAgIGJyZWFrcyA9IDIwMCwNCiAgICAgY2V4LmF4aXMgPSAwLjcsDQogICAgIGxhcyA9IDEsDQogICAgIGNvbCA9ICJza3libHVlIiwNCiAgICAgeGxhYiA9ICJjbHItdHJhbnNmb3JtZWQgbWV0YWJvbG9taWNzIGRhdGEsIGFsbCB0aW1lcyIsDQogICAgIG1haW4gPSAiRGlzdHJpYnV0aW9uIG9mIGNsci10cmFuc2Zvcm1lZCBtZXRhYm9sb21pY3MgZGF0YSwgYWxsIHRpbWVzIikNCmBgYA0KDQpUaGUgZGlzdHJpYnV0aW9uIG9mIG1ldGFib2xvbWljcyBkYXRhIGlzIGNsb3NlIHRvIG5vcm1hbC4NCg0KDQpgYGB7ciBib3hfcGxvdF9tZXRhQl9yYXcsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9DQpib3hwbG90KG1ldGFib2xvbWljc19hbGxfdGltZXNfZGYsDQogICAgICAgIG1haW4gPSAibWV0YWJvbG9taWNzIHJhdyBkYXRhIiwNCiAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUsDQogICAgICAgIGNvbCA9IG1ldGFkYXRhX3RhYmxlX21ldGFCX2FsbF90aW1lcyRjb2xvciwNCiAgICAgICAgY2V4ID0gMC41LA0KICAgICAgICBjZXguYXhpcyA9IDAuOCwNCiAgICAgICAgbGFzID0gMSkNCmBgYA0KDQpgYGB7ciBib3hfcGxvdF9tZXRhQl9jbHIsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9DQpib3hwbG90KG1ldGFib2xvbWljc19hbGxfdGltZXNfY2xyLA0KICAgICAgICBtYWluID0gIm1ldGFib2xvbWljcyBjbHItdHJhbnNmb3JtZWQgZXhwcmVzc2lvbiIsDQogICAgICAgIGhvcml6b250YWwgPSBUUlVFLA0KICAgICAgICBjb2wgPSBtZXRhZGF0YV90YWJsZV9tZXRhQl9hbGxfdGltZXMkY29sb3IsDQogICAgICAgIGNleCA9IDAuNSwNCiAgICAgICAgY2V4LmF4aXMgPSAwLjgsDQogICAgICAgIGxhcyA9IDEpDQpgYGANCg0KDQpUaGUgQ0xSIHRyYW5zZm9ybWF0aW9uIGNlbnRyZWQgb3VyIGRhdGEuDQoNCg0KDQojIyBFeHBsb3JhdG9yeSBzdGF0aXN0aWNhbCBhbmFseXNlcyBvZiB0aGUgd2hvbGUgY29tbXVuaXR5DQoNCiMjIyBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2VzIChQQ0EpIG1ldGF0cmFuc2NyaXB0b21pYw0KDQpgYGB7ciBQQ0FfY2xyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQ0KcGFyKG1mcm93ID0gYygyLDIpKQ0KcmVzX3BjYSA8LSBQQ0EodChjb3VudHNfY2xyKSwgc2NhbGUudW5pdCA9IFRSVUUsIGdyYXBoID0gRkFMU0UpDQpgYGANCg0KYGBge3IgUEVSTUFOT1ZBX2NvbW11bml0eX0NCmNvdW50c19kYXRhIDwtIHQoY291bnRzX2NscikNCm1ldGFkYXRhX3RtcCA8LSBkYXRhLmZyYW1lKG1ldGFkYXRhX3RhYmxlLCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkNCnBlcm1hbm92YSA8LSBhZG9uaXMyKGZvcm11bGEgPSBhcy5mb3JtdWxhKHBhc3RlMCgiY291bnRzX2RhdGF+IiwgImNvbmRpdGlvbiIpKSwgDQogICAgICAgICAgICAgICAgICAgICBkYXRhID0gbWV0YWRhdGFfdG1wLCBtZXRob2Q9ImV1Y2xpZGVhbiIsICMgbWV0aG9kPSJicmF5IiwgI290dV9kYXRhflRJTUUNCiAgICAgICAgICAgICAgICAgICAgIHBlcm11dGF0aW9ucyA9IDk5OSwgc3FydC5kaXN0ID0gRkFMU0UsIGFkZCA9IEZBTFNFLCBieSA9ICJ0ZXJtcyIpDQpwdiA9IHBlcm1hbm92YSRgUHIoPkYpYFsxXQ0KIyBwcmludChwdikNCg0Kcm0oY291bnRzX2RhdGEsIG1ldGFkYXRhX3RtcCkNCmBgYA0KDQpgYGB7ciBQQ0FfMkRfcGxvdHNfY29tbXVuaXR5LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD05fQ0KDQpwY2FfdG1wIDwtIHJiaW5kKHJlc19wY2EkaW5kJGNvb3JkLA0KICAgICAgICAgICAgICAgICByZXNfcGNhJGluZC5zdXAkY29vcmQpICU+JSBkYXRhLmZyYW1lKCkgJT4lIA0KICByb3duYW1lc190b19jb2x1bW4oInNhbXBsZSIpDQoNCg0KcGNhX2RhdGEgPC0gbGVmdF9qb2luKHBjYV90bXAsIHJvd25hbWVzX3RvX2NvbHVtbihtZXRhZGF0YV90YWJsZSksIGJ5PWpvaW5fYnkoInNhbXBsZSIgPT0gInJvd25hbWUiKSkNCnJtKHBjYV90bXApDQoNCkQxX3RleHQgPSBwYXN0ZTAoIkRpbSAxICgiLCANCiAgICAgICAgICAgICAgICAgcm91bmQoZGF0YS5mcmFtZShyZXNfcGNhJGVpZykkcGVyY2VudGFnZS5vZi52YXJpYW5jZVsxXSwgZGlnaXRzPTIpLCANCiAgICAgICAgICAgICAgICAgIiUpIikNCkQyX3RleHQgPSBwYXN0ZTAoIkRpbSAyICgiLCANCiAgICAgICAgICAgICAgICAgcm91bmQoZGF0YS5mcmFtZShyZXNfcGNhJGVpZykkcGVyY2VudGFnZS5vZi52YXJpYW5jZVsyXSwgZGlnaXRzPTIpLCANCiAgICAgICAgICAgICAgICAgIiUpIikNCkQzX3RleHQgPSBwYXN0ZTAoIkRpbSAzICgiLCANCiAgICAgICAgICAgICAgICAgcm91bmQoZGF0YS5mcmFtZShyZXNfcGNhJGVpZykkcGVyY2VudGFnZS5vZi52YXJpYW5jZVszXSwgZGlnaXRzPTIpLCANCiAgICAgICAgICAgICAgICAgIiUpIikNCg0KZ2dwbG90KHBjYV9kYXRhKSArDQogIGdlb21fcG9pbnQoYWVzKHg9RGltLjEsIHk9RGltLjIsIGNvbG91cj1jb2xvciwgKSwgc2l6ZT0zKSArDQogIHNjYWxlX2NvbG91cl9pZGVudGl0eSgiY29uZGl0aW9uIiwgbGFiZWxzPWMoIldOIiwgIlNEIiksIGd1aWRlID0gImxlZ2VuZCIpICsNCiAgZ2dyZXBlbDo6Z2VvbV90ZXh0X3JlcGVsKGFlcyh4PURpbS4xLCB5PURpbS4yLCBjb2xvdXI9Y29sb3IsIGxhYmVsPXNhbXBsZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVkZ2VfeSA9IC0yLCAgc2VlZCA9IDQyLCBzZWdtZW50LnNpemU9MC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIHhsYWIoRDFfdGV4dCkgKyANCiAgeWxhYihEMl90ZXh0KSArDQogIGdndGl0bGUoIlBDQSBtZXRhdHJhbnNjcmlwdG9taWNzIikgKw0KICBsYWJzKGNhcHRpb24gPSAgcGFzdGUwKCJQRVJNQU5PVkEgb24gY29uZGl0aW9uOiBwLXZhbHVlOiAiLCBwdikpICsgDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQ9IGVsZW1lbnRfcmVjdChmaWxsPSIjZjRmNGY0IiksDQogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplPTcpKSAtPiBwMQ0KIA0KDQpnZ3Bsb3QocGNhX2RhdGEpICsNCiAgZ2VvbV9wb2ludChhZXMoeD1EaW0uMSwgeT1EaW0uMywgY29sb3VyPWNvbG9yKSwgc2l6ZT0zKSArDQogIHNjYWxlX2NvbG91cl9pZGVudGl0eSgiY29uZGl0aW9uIiwgbGFiZWxzPWMoIldOIiwgIlNEIiksIGd1aWRlID0gImxlZ2VuZCIpICsNCiAgZ2dyZXBlbDo6Z2VvbV90ZXh0X3JlcGVsKGFlcyh4PURpbS4xLCB5PURpbS4zLCBjb2xvdXI9Y29sb3IsIGxhYmVsPXNhbXBsZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVkZ2VfeSA9IC0yLCAgc2VlZCA9IDQyLCBzZWdtZW50LnNpemU9MC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIHhsYWIoRDFfdGV4dCkgKyANCiAgeWxhYihEM190ZXh0KSArDQogIGdndGl0bGUoIlBDQSBtZXRhdHJhbnNjcmlwdG9taWNzIikgKw0KICBsYWJzKGNhcHRpb24gPSAgcGFzdGUwKCJQRVJNQU5PVkEgb24gY29uZGl0aW9uOiBwLXZhbHVlOiAiLCBwdikpICsgDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQ9IGVsZW1lbnRfcmVjdChmaWxsPSIjZjRmNGY0IiksDQogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplPTcpKSAtPiBwMg0KDQpnZ3Bsb3QocGNhX2RhdGEpICsNCiAgZ2VvbV9wb2ludChhZXMoeD1EaW0uMiwgeT1EaW0uMywgY29sb3VyPWNvbG9yKSwgc2l6ZT0zKSArDQogIHNjYWxlX2NvbG91cl9pZGVudGl0eSgiY29uZGl0aW9uIiwgbGFiZWxzPWMoIldOIiwgIlNEIiksIGd1aWRlID0gImxlZ2VuZCIpICsNCiAgZ2dyZXBlbDo6Z2VvbV90ZXh0X3JlcGVsKGFlcyh4PURpbS4yLCB5PURpbS4zLCBjb2xvdXI9Y29sb3IsIGxhYmVsPXNhbXBsZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVkZ2VfeSA9IC0yLCAgc2VlZCA9IDQyLCBzZWdtZW50LnNpemU9MC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIHhsYWIoRDJfdGV4dCkgKyANCiAgeWxhYihEM190ZXh0KSArDQogIGdndGl0bGUoIlBDQSBtZXRhdHJhbnNjcmlwdG9taWNzIikgKw0KICBsYWJzKGNhcHRpb24gPSAgcGFzdGUwKCJQRVJNQU5PVkEgb24gY29uZGl0aW9uOiBwLXZhbHVlOiAiLCBwdikpICsgDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQ9IGVsZW1lbnRfcmVjdChmaWxsPSIjZjRmNGY0IiksDQogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplPTcpKSAtPiBwMw0KDQpwbG90Z3JpZF9QQ0EgPC0gZ2dhcnJhbmdlKHAxLCBwMiwgcDMsIGxhYmVscyA9IGMoIkEiLCAiQiIsICJDIiksIGNvbW1vbi5sZWdlbmQ9VFJVRSwgbGVnZW5kPSJib3R0b20iLCBucm93PTEpIA0KDQpwcmludChwbG90Z3JpZF9QQ0EpDQoNCmdnc2F2ZShwbG90ID0gcGxvdGdyaWRfUENBLCBmaWxlbmFtZSA9ICIuLi9maWd1cmVzL1BDQV9tZXRhdHJhbnNjcmlwdG9taWNzXzNfY29tcG9zYW50ZXMudGlmZiIsIGRwaSA9IDMwMCwgd2lkdGggPSAxNSwgaGVpZ2h0ID0gNSwgYmc9IndoaXRlIikNCg0KZ2dzYXZlKHBsb3Q9cDEsIGZpbGVuYW1lID0gIi4uL2ZpZ3VyZXMvUENBX21ldGF0cmFuc2NyaXB0b21pY3MudGlmZiIsIGRwaSA9IDMwMCwgd2lkdGggPSA2LCBoZWlnaHQgPSA1LCBiZz0id2hpdGUiKQ0KYGBgDQoNCg0KYGBge3IgM0RfUENBX2Nsciwgd2ViZ2w9VFJVRSwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9NywgbWVzc2FnZT1GQUxTRSwgZXZhbD1UUlVFfQ0KDQpyb3dfY29vcmQgPC0gcmVzX3BjYSRpbmQkY29vcmQNCg0KaW52aXNpYmxlKHJnbDo6b3BlbjNkKCkpDQoNCiNyZ2w6OmJnM2QoImxpZ2h0Z3JheSIpDQpyZ2w6OnBsb3QzZCh4PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAxXSwgDQogICAgICAgICAgICB5PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAyXSwgDQogICAgICAgICAgICB6PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAzXSwNCiAgICAgICAgICAgIHhsYWIgPSBwYXN0ZTAoY29sbmFtZXMocm93X2Nvb3JkKVsxXSAsICIgKCIgLCBzdWJzdHIoYXMuY2hhcmFjdGVyKHJlc19wY2EkZWlnWywyXVsxXSksIDEsIDUpICwgIiUpIiksDQogICAgICAgICAgICB5bGFiID0gcGFzdGUwKGNvbG5hbWVzKHJvd19jb29yZClbMl0gLCAiICgiICwgc3Vic3RyKGFzLmNoYXJhY3RlcihyZXNfcGNhJGVpZ1ssMl1bMl0pLCAxLCA1KSAsICIlKSIpLA0KICAgICAgICAgICAgemxhYiA9IHBhc3RlMChjb2xuYW1lcyhyb3dfY29vcmQpWzNdICwgIiAoIiAsIHN1YnN0cihhcy5jaGFyYWN0ZXIocmVzX3BjYSRlaWdbLDJdWzNdKSwgMSwgNSkgLCAiJSkiKSwNCiAgICAgICAgICAgIHhsaW0gPSBjKG1pbihyb3dfY29vcmRbLCAxXS0xMCksIG1heChyb3dfY29vcmRbLCAxXSkrMTApLCANCiAgICAgICAgICAgIHlsaW0gPSBjKG1pbihyb3dfY29vcmRbLCAyXS0xMCksIG1heChyb3dfY29vcmRbLCAyXSkrMTApLCANCiAgICAgICAgICAgIHpsaW0gPSBjKG1pbihyb3dfY29vcmRbLCAzXS0xMCksIG1heChyb3dfY29vcmRbLCAzXSkrMTApLA0KICAgICAgICAgICAgY29sID0gImRhcmtjeWFuIiwNCiAgICAgICAgICAgIHNpemU9MTAsDQogICAgICAgICAgICBtYWluID0gIlBDQSBjb21tdW5pdHkiKQ0KDQpyZ2w6OnRleHQzZCh4PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAxXSs1LCANCiAgICAgICAgICAgIHk9cm93X2Nvb3JkW2MoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksIDJdKzUsIA0KICAgICAgICAgICAgej1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgM10rNSwNCiAgICAgICAgICAgIHRleHQ9YygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwNCiAgICAgICAgICAgIGNvbCA9ICJkYXJrY3lhbiIsDQogICAgICAgICAgICBzaXplPTEwKQ0KDQoNCnJnbDo6cG9pbnRzM2QoeD1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgMV0sIA0KICAgICAgICAgICAgICB5PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAyXSwgDQogICAgICAgICAgICAgIHo9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDNdLA0KICAgICAgICAgICAgICBjb2wgPSAiZGFya29yYW5nZSIsDQogICAgICAgICAgICAgIHNpemU9MTApDQoNCnJnbDo6dGV4dDNkKHg9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDFdKzUsIA0KICAgICAgICAgICAgeT1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgMl0rNSwgDQogICAgICAgICAgICB6PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAzXSs1LA0KICAgICAgICAgICAgdGV4dD1jKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLA0KICAgICAgICAgICAgY29sID0gImRhcmtvcmFuZ2UiLA0KICAgICAgICAgICAgc2l6ZT0xMCkNCg0KIyBBY3RpdmF0ZSBmb3Igb3IgZ2lmIGdlbmVyYXRpb24NCnBhcjNkKHdpbmRvd1JlY3QgPSBjKDIwLCAzMCwgODAwLCA4MDApKQ0KDQojIHJnbDo6bW92aWUzZCgNCiMgIG1vdmllPSIzZEFuaW1hdGVkX1BDQV9tZXRhVF9jb21tdW5pdHkiLA0KIyAgc3BpbjNkKCBheGlzID0gYygwLCAwLCAxKSwgcnBtID0gMyksDQojICBkdXJhdGlvbiA9IDIwLA0KIyAgZGlyID0gIi4uL2ZpZ3VyZXMiLA0KIyAgdHlwZSA9ICJnaWYiLA0KIyAgY2xlYW4gPSBUUlVFLCB3ZWJzaG90PUZBTFNFLCBmcHM9MjApDQpgYGANCg0KIyMjIFBDQSBtZXRhYm9sb21pY3MNCg0KYGBge3IgUENBX2Nscl9hbGxfdGltZXMsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9DQpwYXIobWZyb3cgPSBjKDIsMikpDQpyZXNfcGNhX21ldGFCX2FsbF90aW1lcyA8LSBQQ0EodChtZXRhYm9sb21pY3NfYWxsX3RpbWVzX2NsciksIHNjYWxlLnVuaXQgPSBUUlVFLCBncmFwaCA9IEZBTFNFKQ0KDQpgYGANCg0KDQpgYGB7ciBQRVJNQU5PVkFfY29tbXVuaXR5X21ldGFCX2FsbF90aW1lc30NCg0KbWV0YWJvbG9taWNzX2RhdGEgPC0gdChtZXRhYm9sb21pY3NfYWxsX3RpbWVzX2NscikNCm1ldGFib2xvbWljc190bXAgPC0gZGF0YS5mcmFtZShtZXRhZGF0YV90YWJsZV9tZXRhQl9hbGxfdGltZXMsIHN0cmluZ3NBc0ZhY3RvcnMgPSBUUlVFKQ0KcGVybWFub3ZhIDwtIGFkb25pczIoZm9ybXVsYSA9IGFzLmZvcm11bGEocGFzdGUwKCJtZXRhYm9sb21pY3NfZGF0YX4iLCAiY29uZGl0aW9uIikpLA0KICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IG1ldGFib2xvbWljc190bXAsIG1ldGhvZD0iZXVjbGlkZWFuIiwgDQogICAgICAgICAgICAgICAgICAgICBwZXJtdXRhdGlvbnMgPSA5OTksIHNxcnQuZGlzdCA9IEZBTFNFLCBhZGQgPSBGQUxTRSwgYnkgPSAidGVybXMiKQ0KcHYgPSBwZXJtYW5vdmEkYFByKD5GKWBbMV0NCiMgcHJpbnQocHYpDQoNCnJtKG1ldGFib2xvbWljc19kYXRhLCBtZXRhYm9sb21pY3NfdG1wKQ0KYGBgDQoNCg0KYGBge3IgUENBXzJEX3Bsb3RzX2NvbW11bml0eV9tZXRhYm9sb21pY3NfYmlzLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD05fQ0KDQpwY2FfdG1wX21ldGFCIDwtIHJiaW5kKHJlc19wY2FfbWV0YUJfYWxsX3RpbWVzJGluZCRjb29yZCwNCiAgICAgICAgICAgICAgICAgcmVzX3BjYV9tZXRhQl9hbGxfdGltZXMkaW5kLnN1cCRjb29yZCkgJT4lIGRhdGEuZnJhbWUoKSAlPiUgDQogIHJvd25hbWVzX3RvX2NvbHVtbigic2FtcGxlIikNCg0KDQpwY2FfZGF0YV9tZXRhQiA8LSBsZWZ0X2pvaW4ocGNhX3RtcF9tZXRhQiwgcm93bmFtZXNfdG9fY29sdW1uKG1ldGFkYXRhX3RhYmxlX21ldGFCX2FsbF90aW1lcyksIGJ5PWpvaW5fYnkoInNhbXBsZSIgPT0gInJvd25hbWUiKSkNCnJtKHBjYV90bXBfbWV0YUIpDQoNCkQxX3RleHQgPSBwYXN0ZTAoIkRpbSAxICgiLCANCiAgICAgICAgICAgICAgICAgcm91bmQoZGF0YS5mcmFtZShyZXNfcGNhX21ldGFCX2FsbF90aW1lcyRlaWcpJHBlcmNlbnRhZ2Uub2YudmFyaWFuY2VbMV0sIGRpZ2l0cz0yKSwgDQogICAgICAgICAgICAgICAgICIlKSIpDQpEMl90ZXh0ID0gcGFzdGUwKCJEaW0gMiAoIiwgDQogICAgICAgICAgICAgICAgIHJvdW5kKGRhdGEuZnJhbWUocmVzX3BjYV9tZXRhQl9hbGxfdGltZXMkZWlnKSRwZXJjZW50YWdlLm9mLnZhcmlhbmNlWzJdLCBkaWdpdHM9MiksIA0KICAgICAgICAgICAgICAgICAiJSkiKQ0KRDNfdGV4dCA9IHBhc3RlMCgiRGltIDMgKCIsIA0KICAgICAgICAgICAgICAgICByb3VuZChkYXRhLmZyYW1lKHJlc19wY2FfbWV0YUJfYWxsX3RpbWVzJGVpZykkcGVyY2VudGFnZS5vZi52YXJpYW5jZVszXSwgZGlnaXRzPTIpLCANCiAgICAgICAgICAgICAgICAgIiUpIikNCg0KZ2dwbG90KHBjYV9kYXRhX21ldGFCKSArDQogIGdlb21fcG9pbnQoYWVzKHg9RGltLjEsIHk9RGltLjIsIGNvbG91cj1jb2xvciwgKSwgc2l6ZT0zKSArDQogIHNjYWxlX2NvbG91cl9pZGVudGl0eSgiY29uZGl0aW9uIiwgbGFiZWxzPWMoIldOIiwgIlNEIiksIGd1aWRlID0gImxlZ2VuZCIpICsNCiAgZ2dyZXBlbDo6Z2VvbV90ZXh0X3JlcGVsKGFlcyh4PURpbS4xLCB5PURpbS4yLCBjb2xvdXI9Y29sb3IsIGxhYmVsPXNhbXBsZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVkZ2VfeSA9IC0yLCAgc2VlZCA9IDQyLCBzZWdtZW50LnNpemU9MC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIHhsYWIoRDFfdGV4dCkgKyANCiAgeWxhYihEMl90ZXh0KSArDQogIGdndGl0bGUoIlBDQSBtZXRhLW1lYm9sb21pY3MiKSArDQogIGxhYnMoY2FwdGlvbiA9ICBwYXN0ZTAoIlBFUk1BTk9WQSBvbiBjb25kaXRpb246IHAtdmFsdWU6ICIsIHB2KSkgKyANCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZD0gZWxlbWVudF9yZWN0KGZpbGw9IiNmNGY0ZjQiKSwNCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemU9NykpIC0+IHAxX21ldGFCDQogDQoNCmdncGxvdChwY2FfZGF0YV9tZXRhQikgKw0KICBnZW9tX3BvaW50KGFlcyh4PURpbS4xLCB5PURpbS4zLCBjb2xvdXI9Y29sb3IpLCBzaXplPTMpICsNCiAgc2NhbGVfY29sb3VyX2lkZW50aXR5KCJjb25kaXRpb24iLCBsYWJlbHM9YygiV04iLCAiU0QiKSwgZ3VpZGUgPSAibGVnZW5kIikgKw0KICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoYWVzKHg9RGltLjEsIHk9RGltLjMsIGNvbG91cj1jb2xvciwgbGFiZWw9c2FtcGxlKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBudWRnZV95ID0gLTIsICBzZWVkID0gNDIsIHNlZ21lbnQuc2l6ZT0wLjEsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgeGxhYihEMV90ZXh0KSArIA0KICB5bGFiKEQzX3RleHQpICsNCiAgZ2d0aXRsZSgiUENBIG1ldGEtbWVib2xvbWljcyIpICsNCiAgbGFicyhjYXB0aW9uID0gIHBhc3RlMCgiUEVSTUFOT1ZBIG9uIGNvbmRpdGlvbjogcC12YWx1ZTogIiwgcHYpKSArIA0KICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kPSBlbGVtZW50X3JlY3QoZmlsbD0iI2Y0ZjRmNCIpLA0KICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZT03KSkgLT4gcDJfbWV0YUINCg0KZ2dwbG90KHBjYV9kYXRhX21ldGFCKSArDQogIGdlb21fcG9pbnQoYWVzKHg9RGltLjIsIHk9RGltLjMsIGNvbG91cj1jb2xvciksIHNpemU9MykgKw0KICBzY2FsZV9jb2xvdXJfaWRlbnRpdHkoImNvbmRpdGlvbiIsIGxhYmVscz1jKCJXTiIsICJTRCIpLCBndWlkZSA9ICJsZWdlbmQiKSArDQogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChhZXMoeD1EaW0uMiwgeT1EaW0uMywgY29sb3VyPWNvbG9yLCBsYWJlbD1zYW1wbGUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG51ZGdlX3kgPSAtMiwgIHNlZWQgPSA0Miwgc2VnbWVudC5zaXplPTAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICB4bGFiKEQyX3RleHQpICsgDQogIHlsYWIoRDNfdGV4dCkgKw0KICBnZ3RpdGxlKCJQQ0EgbWV0YS1tZWJvbG9taWNzIikgKw0KICBsYWJzKGNhcHRpb24gPSAgcGFzdGUwKCJQRVJNQU5PVkEgb24gY29uZGl0aW9uOiBwLXZhbHVlOiAiLCBwdikpICsgDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQ9IGVsZW1lbnRfcmVjdChmaWxsPSIjZjRmNGY0IiksDQogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplPTcpKSAtPiBwM19tZXRhQg0KDQpwbG90Z3JpZF9QQ0FfbWV0YUIgPC0gZ2dhcnJhbmdlKHAxX21ldGFCLCBwMl9tZXRhQiwgcDNfbWV0YUIsIGxhYmVscyA9IGMoIkEiLCAiQiIsICJDIiksIGNvbW1vbi5sZWdlbmQ9VFJVRSwgbGVnZW5kPSJib3R0b20iLCBucm93PTEpIA0KDQpwcmludChwbG90Z3JpZF9QQ0FfbWV0YUIpDQoNCmdnc2F2ZShwbG90ID0gcDFfbWV0YUIsIGZpbGVuYW1lID0gIi4uL2ZpZ3VyZXMvUENBX21ldGFib2xvbWljc19hbGxfdGltZXMudGlmZiIsIGRwaSA9IDMwMCwgd2lkdGggPSA1LCBoZWlnaHQgPSA1LCBiZz0id2hpdGUiKQ0KDQpnZ3NhdmUocGxvdCA9IHBsb3RncmlkX1BDQV9tZXRhQiwgZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9QQ0FfbWV0YWJvbG9taWNzXzNfY29tcG9zYW50ZXNfYWxsX3RpbWVzLnRpZmYiLCBkcGkgPSAzMDAsIHdpZHRoID0gMTUsIGhlaWdodCA9IDUsIGJnPSJ3aGl0ZSIpDQoNCmdnc2F2ZShwbG90PXAxX21ldGFCLCBmaWxlbmFtZSA9ICIuLi9maWd1cmVzL1BDQV9tZXRhYm9sb21pY3NfYWxsX3RpbWVzLnRpZmYiLCBkcGkgPSAzMDAsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNSwgYmc9IndoaXRlIikNCmBgYA0KDQpgYGB7ciAzRF9QQ0FfbWV0YUJfY2xyX2FsbF90aW1lcG9pbnRzLCB3ZWJnbD1UUlVFLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03LCBtZXNzYWdlPUZBTFNFfQ0KDQpyb3dfY29vcmQgPC0gcmVzX3BjYV9tZXRhQl9hbGxfdGltZXMkaW5kJGNvb3JkDQoNCmludmlzaWJsZShyZ2w6Om9wZW4zZCgpKQ0KDQojcmdsOjpiZzNkKCJsaWdodGdyYXkiKQ0KcmdsOjpwbG90M2QoeD1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgMV0sIA0KICAgICAgICAgICAgeT1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgMl0sIA0KICAgICAgICAgICAgej1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgM10sDQogICAgICAgICAgICB4bGFiID0gcGFzdGUwKGNvbG5hbWVzKHJvd19jb29yZClbMV0gLCAiICgiICwgc3Vic3RyKGFzLmNoYXJhY3RlcihyZXNfcGNhJGVpZ1ssMl1bMV0pLCAxLCA1KSAsICIlKSIpLA0KICAgICAgICAgICAgeWxhYiA9IHBhc3RlMChjb2xuYW1lcyhyb3dfY29vcmQpWzJdICwgIiAoIiAsIHN1YnN0cihhcy5jaGFyYWN0ZXIocmVzX3BjYSRlaWdbLDJdWzJdKSwgMSwgNSkgLCAiJSkiKSwNCiAgICAgICAgICAgIHpsYWIgPSBwYXN0ZTAoY29sbmFtZXMocm93X2Nvb3JkKVszXSAsICIgKCIgLCBzdWJzdHIoYXMuY2hhcmFjdGVyKHJlc19wY2EkZWlnWywyXVszXSksIDEsIDUpICwgIiUpIiksDQogICAgICAgICAgICB4bGltID0gYyhtaW4ocm93X2Nvb3JkWywgMV0tMTApLCBtYXgocm93X2Nvb3JkWywgMV0pKzEwKSwgDQogICAgICAgICAgICB5bGltID0gYyhtaW4ocm93X2Nvb3JkWywgMl0tMTApLCBtYXgocm93X2Nvb3JkWywgMl0pKzEwKSwgDQogICAgICAgICAgICB6bGltID0gYyhtaW4ocm93X2Nvb3JkWywgM10tMTApLCBtYXgocm93X2Nvb3JkWywgM10pKzEwKSwNCiAgICAgICAgICAgIGNvbCA9ICJkYXJrY3lhbiIsDQogICAgICAgICAgICBzaXplPTEwLA0KICAgICAgICAgICAgbWFpbiA9ICJQQ0EgbWV0YS1tZXRhYm9sb21pY3MgY29tbXVuaXR5IikNCg0KcmdsOjp0ZXh0M2QoeD1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgMV0rNSwgDQogICAgICAgICAgICB5PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAyXSs1LCANCiAgICAgICAgICAgIHo9cm93X2Nvb3JkW2MoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksIDNdKzUsDQogICAgICAgICAgICB0ZXh0PWMoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksDQogICAgICAgICAgICBjb2wgPSAiZGFya2N5YW4iLA0KICAgICAgICAgICAgc2l6ZT0xMCkNCg0KDQpyZ2w6OnBvaW50czNkKHg9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDFdLCANCiAgICAgICAgICAgICAgeT1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgMl0sIA0KICAgICAgICAgICAgICB6PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAzXSwNCiAgICAgICAgICAgICAgY29sID0gImRhcmtvcmFuZ2UiLA0KICAgICAgICAgICAgICBzaXplPTEwKQ0KDQpyZ2w6OnRleHQzZCh4PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAxXSs1LCANCiAgICAgICAgICAgIHk9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDJdKzUsIA0KICAgICAgICAgICAgej1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgM10rNSwNCiAgICAgICAgICAgIHRleHQ9YygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwNCiAgICAgICAgICAgIGNvbCA9ICJkYXJrb3JhbmdlIiwNCiAgICAgICAgICAgIHNpemU9MTApDQoNCg0KcmdsOjpwb2ludHMzZCh4PXJvd19jb29yZFtjKCJXTl9UMF8xIiwgIldOX1QwXzIiLCAiV05fVDBfMyIpLCAxXSwgDQogICAgICAgICAgICAgIHk9cm93X2Nvb3JkW2MoIldOX1QwXzEiLCAiV05fVDBfMiIsICJXTl9UMF8zIiksIDJdLCANCiAgICAgICAgICAgICAgej1yb3dfY29vcmRbYygiV05fVDBfMSIsICJXTl9UMF8yIiwgIldOX1QwXzMiKSwgM10sDQogICAgICAgICAgICAgIGNvbCA9ICJkYXJrY3lhbiIsDQogICAgICAgICAgICAgIHNpemU9MTApDQoNCnJnbDo6dGV4dDNkKHg9cm93X2Nvb3JkW2MoIldOX1QwXzEiLCAiV05fVDBfMiIsICJXTl9UMF8zIiksIDFdKzUsIA0KICAgICAgICAgICAgeT1yb3dfY29vcmRbYygiV05fVDBfMSIsICJXTl9UMF8yIiwgIldOX1QwXzMiKSwgMl0rNSwgDQogICAgICAgICAgICB6PXJvd19jb29yZFtjKCJXTl9UMF8xIiwgIldOX1QwXzIiLCAiV05fVDBfMyIpLCAzXSs1LA0KICAgICAgICAgICAgdGV4dD1jKCJXTl9UMF8xIiwgIldOX1QwXzIiLCAiV05fVDBfMyIpLA0KICAgICAgICAgICAgY29sID0gImRhcmtjeWFuIiwNCiAgICAgICAgICAgIHNpemU9MTApDQoNCg0KcmdsOjpwb2ludHMzZCh4PXJvd19jb29yZFtjKCJTRF9UMF8xIiwgIlNEX1QwXzIiLCAiU0RfVDBfMyIpLCAxXSwgDQogICAgICAgICAgICAgIHk9cm93X2Nvb3JkW2MoIlNEX1QwXzEiLCAiU0RfVDBfMiIsICJTRF9UMF8zIiksIDJdLCANCiAgICAgICAgICAgICAgej1yb3dfY29vcmRbYygiU0RfVDBfMSIsICJTRF9UMF8yIiwgIlNEX1QwXzMiKSwgM10sDQogICAgICAgICAgICAgIGNvbCA9ICJkYXJrb3JhbmdlIiwNCiAgICAgICAgICAgICAgc2l6ZT0xMCkNCg0KcmdsOjp0ZXh0M2QoeD1yb3dfY29vcmRbYygiU0RfVDBfMSIsICJTRF9UMF8yIiwgIlNEX1QwXzMiKSwgMV0rNSwgDQogICAgICAgICAgICB5PXJvd19jb29yZFtjKCJTRF9UMF8xIiwgIlNEX1QwXzIiLCAiU0RfVDBfMyIpLCAyXSs1LCANCiAgICAgICAgICAgIHo9cm93X2Nvb3JkW2MoIlNEX1QwXzEiLCAiU0RfVDBfMiIsICJTRF9UMF8zIiksIDNdKzUsDQogICAgICAgICAgICB0ZXh0PWMoIlNEX1QwXzEiLCAiU0RfVDBfMiIsICJTRF9UMF8zIiksDQogICAgICAgICAgICBjb2wgPSAiZGFya29yYW5nZSIsDQogICAgICAgICAgICBzaXplPTEwKQ0KDQoNCg0KIyBBY3RpdmF0ZSBmb3Igb3IgZ2lmIGdlbmVyYXRpb24NCiMgcGFyM2Qod2luZG93UmVjdCA9IGMoMjAsIDMwLCA4MDAsIDgwMCkpDQojIA0KIyByZ2w6Om1vdmllM2QoDQojICBtb3ZpZT0iM2RBbmltYXRlZF9QQ0FfbWV0YUJfY29tbXVuaXR5IiwNCiMgIHNwaW4zZCggYXhpcyA9IGMoMCwgMCwgMSksIHJwbSA9IDMpLA0KIyAgZHVyYXRpb24gPSAyMCwNCiMgIGRpciA9ICIuLi9maWd1cmVzIiwNCiMgIHR5cGUgPSAiZ2lmIiwNCiMgIGNsZWFuID0gVFJVRSwgd2Vic2hvdD1GQUxTRSwgZnBzPTIwKQ0KYGBgDQoNCg0KIyMgSW5kaXZpZHVhbCBleHBsb3JhdG9yeSBhbmFseXNpcyBvZiBtZXRhdHJhbnNjcmlwdG9taWNzIGRhdGEgYnkgc3BlY2llcw0KDQojIyMjIERhdGEgcHJlcGFyYXRpb24NCg0KIyMjIyBMb2FkIGRhdGEgYnkgc3BlY2llcw0KDQpgYGB7ciByZWNvdmVyX3NwZWNpZXNfZGF0YX0NCg0KZGlvaHVfZ2VuZWlkIDwtIGFubm90YXRpb25fdGFibGUkT3JnYW5pc20gPT0gIkQuaHVuZ2FyaWNhIg0KZGlvaHVfZGYgPC0gY291bnRzX3N0YW5kYXJkW3N0YXJ0c1dpdGgocm93bmFtZXNfdG9fY29sdW1uKGNvdW50c19zdGFuZGFyZCkkcm93bmFtZSwgIkQuaHVuZ2FyaWNhIiksXQ0KDQpwc2VzeV9nZW5laWQgPC0gYW5ub3RhdGlvbl90YWJsZSRPcmdhbmlzbSA9PSAiUC5zeXJpbmdhZSINCnBzZXN5X2RmIDwtIGNvdW50c19zdGFuZGFyZFtzdGFydHNXaXRoKHJvd25hbWVzX3RvX2NvbHVtbihjb3VudHNfc3RhbmRhcmQpJHJvd25hbWUsICJQLnN5cmluZ2FlIiksXQ0KDQpwc2Vncl9nZW5laWQgPC0gYW5ub3RhdGlvbl90YWJsZSRPcmdhbmlzbSA9PSAiUC5ncmFtaW5pcyINCnBzZWdyX2RmIDwtIGNvdW50c19zdGFuZGFyZFtzdGFydHNXaXRoKHJvd25hbWVzX3RvX2NvbHVtbihjb3VudHNfc3RhbmRhcmQpJHJvd25hbWUsICJQLmdyYW1pbmlzIiksXQ0KDQpyaG9lbl9nZW5laWQgPC0gYW5ub3RhdGlvbl90YWJsZSRPcmdhbmlzbSA9PSAiUi5lbmNsZW5zaXMiDQpyaG9lbl9kZiA8LSBjb3VudHNfc3RhbmRhcmRbc3RhcnRzV2l0aChyb3duYW1lc190b19jb2x1bW4oY291bnRzX3N0YW5kYXJkKSRyb3duYW1lLCAiUi5lbmNsZW5zaXMiKSxdDQoNCmBgYA0KDQojIyMjIFplcm9lcyBzbW9vdGhpbmcgYnkgc3BlY2llcw0KDQpgYGB7ciB6ZXJvZXNfc21vb3RoaW5nX3NwZV9kYXRhfQ0KDQojIyByZW1haW5pbmcgemVyb2VzIHNtb290aGluZyAoYXMgaW4gWmhhbmcgZXQgYWwuIDIwMjEpDQptaW5fdmFsIDwtIGFwcGx5KGRpb2h1X2RmLCAxLCBmdW5jdGlvbih4KSAobWluKHhbeD4wXSkvMikpDQpmb3IgKGdlbmUgaW4gcm93Lm5hbWVzKGRpb2h1X2RmKSkgew0KICBkaW9odV9kZltnZW5lLF1bZGlvaHVfZGZbZ2VuZSxdID09IDBdIDwtIG1pbl92YWxbZ2VuZV0NCn0NCg0KbWluX3ZhbCA8LSBhcHBseShwc2VzeV9kZiwgMSwgZnVuY3Rpb24oeCkgKG1pbih4W3g+MF0pLzIpKQ0KZm9yIChnZW5lIGluIHJvdy5uYW1lcyhwc2VzeV9kZikpIHsNCiAgcHNlc3lfZGZbZ2VuZSxdW3BzZXN5X2RmW2dlbmUsXSA9PSAwXSA8LSBtaW5fdmFsW2dlbmVdDQp9DQoNCm1pbl92YWwgPC0gYXBwbHkocHNlZ3JfZGYsIDEsIGZ1bmN0aW9uKHgpIChtaW4oeFt4PjBdKS8yKSkNCmZvciAoZ2VuZSBpbiByb3cubmFtZXMocHNlZ3JfZGYpKSB7DQogIHBzZWdyX2RmW2dlbmUsXVtwc2Vncl9kZltnZW5lLF0gPT0gMF0gPC0gbWluX3ZhbFtnZW5lXQ0KfQ0KDQptaW5fdmFsIDwtIGFwcGx5KHJob2VuX2RmLCAxLCBmdW5jdGlvbih4KSAobWluKHhbeD4wXSkvMikpDQpmb3IgKGdlbmUgaW4gcm93Lm5hbWVzKHJob2VuX2RmKSkgew0KICByaG9lbl9kZltnZW5lLF1bcmhvZW5fZGZbZ2VuZSxdID09IDBdIDwtIG1pbl92YWxbZ2VuZV0NCn0NCmBgYA0KDQojIyMjIENMUiBUcmFuc2Zvcm1hdGlvbiBvZiBjb3VudHMgYnkgc3BlY2llcyANCg0KYGBge3IgY2xyX3RyYW5zZm9ybWF0aW9uX29mX3NwZV9kYXRhfQ0KZGlvaHVfY2xyIDwtIGRpb2h1X2RmDQpwc2VzeV9jbHIgPC0gcHNlc3lfZGYNCnBzZWdyX2NsciA8LSBwc2Vncl9kZg0KcmhvZW5fY2xyIDwtIHJob2VuX2RmDQoNCmZvciAoc2FtcCBpbiBzYW1wbGVzKSB7DQogICAgZGlvaHVfY2xyWyxzYW1wXSA8LSBhcy52ZWN0b3IoY2xyKGRpb2h1X2RmWyxzYW1wXSkpDQogICAgcHNlc3lfY2xyWyxzYW1wXSA8LSBhcy52ZWN0b3IoY2xyKHBzZXN5X2RmWyxzYW1wXSkpDQogICAgcHNlZ3JfY2xyWyxzYW1wXSA8LSBhcy52ZWN0b3IoY2xyKHBzZWdyX2RmWyxzYW1wXSkpDQogICAgcmhvZW5fY2xyWyxzYW1wXSA8LSBhcy52ZWN0b3IoY2xyKHJob2VuX2RmWyxzYW1wXSkpDQp9DQoNCmBgYA0KDQoNCiMjIyBUcmFuc2NyaXB0b21pY3MgY291bnRzIGhpc3RvZ3JhbXMgYnkgc3BlY2llcyB7LnRhYnNldH0NCg0KIyMjIyAqRGlvc3plZ2lhIGh1bmdhcmljYSoNCg0KYGBge3IgaGlzdF9jbHJfZGlvaHUsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9DQpwYXIobWZyb3c9YygxLDEpKQ0KaGlzdCh1bmxpc3QoZGlvaHVfY2xyKSwNCiAgICAgYnJlYWtzID0gMjAwLA0KICAgICBjZXguYXhpcyA9IDAuNywNCiAgICAgbGFzID0gMSwNCiAgICAgY29sID0gInNreWJsdWUiLA0KICAgICB5bGltID0gYygwLDE4MDApLA0KICAgICB4bGltID0gYygtNSwxNSksDQogICAgIHhsYWIgPSAiY2xyLXRyYW5zZm9ybWVkIGNvdW50cyIsDQogICAgIG1haW4gPSAiRGlzdHJpYnV0aW9uIG9mIEQuIGh1bmdhcmljYSBjbHItdHJhbnNmb3JtZWQgY291bnRzIikNCmBgYA0KDQojIyMjICpQc2V1ZG9tb25hcyBncmFtaW5pcyoNCg0KYGBge3IgaGlzdF9jbHJfcHNlZ3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9DQpwYXIobWZyb3c9YygxLDEpKQ0KaGlzdCh1bmxpc3QocHNlZ3JfY2xyKSwNCiAgICAgYnJlYWtzID0gMjAwLA0KICAgICBjZXguYXhpcyA9IDAuNywNCiAgICAgbGFzID0gMSwNCiAgICAgY29sID0gInNreWJsdWUiLA0KICAgICB5bGltID0gYygwLDE4MDApLA0KICAgICB4bGltID0gYygtNSwxNSksDQogICAgIHhsYWIgPSAiY2xyLXRyYW5zZm9ybWVkIGNvdW50cyIsDQogICAgIG1haW4gPSAiRGlzdHJpYnV0aW9uIG9mIFAuIGdyYW1pbmlzIGNsci10cmFuc2Zvcm1lZCBjb3VudHMiKQ0KYGBgDQoNClZlcnkgZmV3ICpQLiBncmFtaW5pcyogY291bnRzLCBwcm9iYWJseSBub3QgZXhwbG9pdGFibGUuDQoNCiMjIyMgKlBzZXVkb21vbmFzIHN5cmluZ2FlKg0KDQpgYGB7ciBoaXN0X2Nscl9wc2VzeSwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9N30NCnBhcihtZnJvdz1jKDEsMSkpDQpoaXN0KHVubGlzdChwc2VzeV9jbHIpLA0KICAgICBicmVha3MgPSAyMDAsDQogICAgIGNleC5heGlzID0gMC43LA0KICAgICBsYXMgPSAxLA0KICAgICBjb2wgPSAic2t5Ymx1ZSIsDQogICAgIHlsaW0gPSBjKDAsMTgwMCksDQogICAgIHhsaW0gPSBjKC01LDE1KSwNCiAgICAgeGxhYiA9ICJjbHItdHJhbnNmb3JtZWQgY291bnRzIiwNCiAgICAgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgUC4gc3lyaW5nYWUgY2xyLXRyYW5zZm9ybWVkIGNvdW50cyIpDQpgYGANCg0KIyMjIyAqUmhvZG9jb2NjdXMgZW5jbGVuc2lzKg0KDQpgYGB7ciBoaXN0X2Nscl9yaG9lbiwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9N30NCnBhcihtZnJvdz1jKDEsMSkpDQpoaXN0KHVubGlzdChyaG9lbl9jbHIpLA0KICAgICBicmVha3MgPSAyMDAsDQogICAgIGNleC5heGlzID0gMC43LA0KICAgICBsYXMgPSAxLA0KICAgICBjb2wgPSAic2t5Ymx1ZSIsDQogICAgIHlsaW0gPSBjKDAsMTgwMCksDQogICAgIHhsaW0gPSBjKC01LDE1KSwNCiAgICAgeGxhYiA9ICJjbHItdHJhbnNmb3JtZWQgY291bnRzIiwNCiAgICAgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgUi4gZW5jbGVuc2lzIGNsci10cmFuc2Zvcm1lZCBjb3VudHMiKQ0KYGBgDQoNCiMjIyBUcmFuc2NyaXB0b21pY3MgY291bnRzIGJveC1wbG90cyBieSBzcGVjaWVzIHsudGFic2V0fQ0KDQojIyMjICpEaW9zemVnaWEgaHVuZ2FyaWNhKg0KDQpgYGB7ciBib3hfcGxvdF9jbHJfZGlvaHUsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9DQpib3hwbG90KGRpb2h1X2NsciwNCiAgICAgICAgbWFpbiA9ICJELiBodW5nYXJpY2EgY2xyLXRyYW5zZm9ybWVkIGV4cHJlc3Npb24iLA0KICAgICAgICBob3Jpem9udGFsID0gVFJVRSwNCiAgICAgICAgY29sID0gbWV0YWRhdGFfdGFibGUkY29sb3IsDQogICAgICAgIGNleCA9IDAuNSwNCiAgICAgICAgY2V4LmF4aXMgPSAwLjgsDQogICAgICAgIGxhcyA9IDEpDQoNCmBgYA0KDQojIyMjICpQc2V1ZG9tb25hcyBncmFtaW5pcyoNCg0KYGBge3IgYm94X3Bsb3RfY2xyX3BzZWdyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQ0KYm94cGxvdChwc2Vncl9jbHIsDQogICAgICAgIG1haW4gPSAiUC4gZ3JhbWluaXMgY2xyLXRyYW5zZm9ybWVkIGV4cHJlc3Npb24iLA0KICAgICAgICBob3Jpem9udGFsID0gVFJVRSwNCiAgICAgICAgY29sID0gbWV0YWRhdGFfdGFibGUkY29sb3IsDQogICAgICAgIGNleCA9IDAuNSwNCiAgICAgICAgY2V4LmF4aXMgPSAwLjgsDQogICAgICAgIGxhcyA9IDEpDQoNCmBgYA0KDQojIyMjICpQc2V1ZG9tb25hcyBzeXJpbmdhZSoNCg0KYGBge3IgYm94X3Bsb3RfY2xyX3BzZXN5LCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQ0KYm94cGxvdChwc2VzeV9jbHIsDQogICAgICAgIG1haW4gPSAiUC4gc3lyaW5nYWUgY2xyLXRyYW5zZm9ybWVkIGV4cHJlc3Npb24iLA0KICAgICAgICBob3Jpem9udGFsID0gVFJVRSwNCiAgICAgICAgY29sID0gbWV0YWRhdGFfdGFibGUkY29sb3IsDQogICAgICAgIGNleCA9IDAuNSwNCiAgICAgICAgY2V4LmF4aXMgPSAwLjgsDQogICAgICAgIGxhcyA9IDEpDQoNCmBgYA0KDQojIyMjICpSaG9kb2NvY2N1cyBlbmNsZW5zaXMqDQoNCmBgYHtyIGJveF9wbG90X2Nscl9yaG9lbiwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9N30NCmJveHBsb3QocmhvZW5fY2xyLA0KICAgICAgICBtYWluID0gIlIuIGVuY2xlbnNpcyBjbHItdHJhbnNmb3JtZWQgZXhwcmVzc2lvbiIsDQogICAgICAgIGhvcml6b250YWwgPSBUUlVFLA0KICAgICAgICBjb2wgPSBtZXRhZGF0YV90YWJsZSRjb2xvciwNCiAgICAgICAgY2V4ID0gMC41LA0KICAgICAgICBjZXguYXhpcyA9IDAuOCwNCiAgICAgICAgbGFzID0gMSkNCg0KYGBgDQoNCiMjIyBUcmFuc2NyaXB0b21pY3MgY291bnRzIFBDQSBieSBzcGVjaWVzIHsudGFic2V0fQ0KDQojIyMjICpEaW9zemVnaWEgaHVuZ2FyaWNhKg0KDQpgYGB7ciBQQ0FfY2xyX2Rpb2h1fQ0KDQpyZXNfcGNhIDwtIFBDQSh0KGRpb2h1X2NsciksIHNjYWxlLnVuaXQgPSBUUlVFLCBncmFwaCA9IEZBTFNFKQ0KDQojZnZpel9wY2FfaW5kKHJlc19wY2EsDQojICAgICAgICAgICAgIGNvbC5pbmQgPSBtZXRhZGF0YV90YWJsZSRjb2xvciwNCiMgICAgICAgICAgICAgbWVhbi5wb2ludCA9IEZBTFNFLA0KIyAgICAgICAgICAgICB0aXRsZSA9ICJQQ0Egb24gRC4gaHVuZ2FyaWNhIGNsci10cmFuc2Zvcm1lZCBjb3VudHMiKQ0KYGBgDQoNCmBgYHtyIFBFUk1BTk9WQV9kaW9odX0NCmNvdW50c19kYXRhIDwtIHQoZGlvaHVfY2xyKQ0KbWV0YWRhdGFfdG1wIDwtIGRhdGEuZnJhbWUobWV0YWRhdGFfdGFibGUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBUUlVFKQ0KcGVybWFub3ZhIDwtIGFkb25pczIoZm9ybXVsYSA9IGFzLmZvcm11bGEocGFzdGUwKCJjb3VudHNfZGF0YX4iLCAiY29uZGl0aW9uIikpLCANCiAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBtZXRhZGF0YV90bXAsIG1ldGhvZD0iZXVjbGlkZWFuIiwgIyBtZXRob2Q9ImJyYXkiLCAjb3R1X2RhdGF+VElNRQ0KICAgICAgICAgICAgICAgICAgICAgcGVybXV0YXRpb25zID0gOTk5LCBzcXJ0LmRpc3QgPSBGQUxTRSwgYWRkID0gRkFMU0UsIGJ5ID0gInRlcm1zIikNCnB2ID0gcGVybWFub3ZhJGBQcig+RilgWzFdDQojIHByaW50KHB2KQ0KDQpybShjb3VudHNfZGF0YSwgbWV0YWRhdGFfdG1wKQ0KYGBgDQoNCmBgYHtyIFBDQV8yRF9wbG90c19kaW9odSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OX0NCg0KcGNhX3RtcCA8LSByYmluZChyZXNfcGNhJGluZCRjb29yZCwNCiAgICAgICAgICAgICAgICAgcmVzX3BjYSRpbmQuc3VwJGNvb3JkKSAlPiUgZGF0YS5mcmFtZSgpICU+JSANCiAgcm93bmFtZXNfdG9fY29sdW1uKCJzYW1wbGUiKQ0KDQoNCnBjYV9kYXRhIDwtIGxlZnRfam9pbihwY2FfdG1wLCByb3duYW1lc190b19jb2x1bW4obWV0YWRhdGFfdGFibGUpLCBieT1qb2luX2J5KCJzYW1wbGUiID09ICJyb3duYW1lIikpDQpybShwY2FfdG1wKQ0KDQpEMV90ZXh0ID0gcGFzdGUwKCJEaW0gMSAoIiwgDQogICAgICAgICAgICAgICAgIHJvdW5kKGRhdGEuZnJhbWUocmVzX3BjYSRlaWcpJHBlcmNlbnRhZ2Uub2YudmFyaWFuY2VbMV0sIGRpZ2l0cz0yKSwgDQogICAgICAgICAgICAgICAgICIlKSIpDQpEMl90ZXh0ID0gcGFzdGUwKCJEaW0gMiAoIiwgDQogICAgICAgICAgICAgICAgIHJvdW5kKGRhdGEuZnJhbWUocmVzX3BjYSRlaWcpJHBlcmNlbnRhZ2Uub2YudmFyaWFuY2VbMl0sIGRpZ2l0cz0yKSwgDQogICAgICAgICAgICAgICAgICIlKSIpDQpEM190ZXh0ID0gcGFzdGUwKCJEaW0gMyAoIiwgDQogICAgICAgICAgICAgICAgIHJvdW5kKGRhdGEuZnJhbWUocmVzX3BjYSRlaWcpJHBlcmNlbnRhZ2Uub2YudmFyaWFuY2VbM10sIGRpZ2l0cz0yKSwgDQogICAgICAgICAgICAgICAgICIlKSIpDQoNCmdncGxvdChwY2FfZGF0YSkgKw0KICBnZW9tX3BvaW50KGFlcyh4PURpbS4xLCB5PURpbS4yLCBjb2xvdXI9Y29sb3IsICksIHNpemU9MykgKw0KICBzY2FsZV9jb2xvdXJfaWRlbnRpdHkoImNvbmRpdGlvbiIsIGxhYmVscz1jKCJXTiIsICJTRCIpLCBndWlkZSA9ICJsZWdlbmQiKSArDQogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChhZXMoeD1EaW0uMSwgeT1EaW0uMiwgY29sb3VyPWNvbG9yLCBsYWJlbD1zYW1wbGUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG51ZGdlX3kgPSAtMiwgIHNlZWQgPSA0Miwgc2VnbWVudC5zaXplPTAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICB4bGFiKEQxX3RleHQpICsgDQogIHlsYWIoRDJfdGV4dCkgKw0KICBnZ3RpdGxlKCJQQ0EgbWV0YXRyYW5zY3JpcHRvbWljcyAgXG5ELiBodW5nYXJpY2EiKSArDQogIGxhYnMoY2FwdGlvbiA9ICBwYXN0ZTAoIlBFUk1BTk9WQSBvbiBjb25kaXRpb246IHAtdmFsdWU6ICIsIHB2KSkgKyANCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZD0gZWxlbWVudF9yZWN0KGZpbGw9IiNmNGY0ZjQiKSwNCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemU9NykpIC0+IHAxDQogDQoNCmdncGxvdChwY2FfZGF0YSkgKw0KICBnZW9tX3BvaW50KGFlcyh4PURpbS4xLCB5PURpbS4zLCBjb2xvdXI9Y29sb3IpLCBzaXplPTMpICsNCiAgc2NhbGVfY29sb3VyX2lkZW50aXR5KCJjb25kaXRpb24iLCBsYWJlbHM9YygiV04iLCAiU0QiKSwgZ3VpZGUgPSAibGVnZW5kIikgKw0KICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoYWVzKHg9RGltLjEsIHk9RGltLjMsIGNvbG91cj1jb2xvciwgbGFiZWw9c2FtcGxlKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBudWRnZV95ID0gLTIsICBzZWVkID0gNDIsIHNlZ21lbnQuc2l6ZT0wLjEsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgeGxhYihEMV90ZXh0KSArIA0KICB5bGFiKEQzX3RleHQpICsNCiAgZ2d0aXRsZSgiUENBIG1ldGF0cmFuc2NyaXB0b21pY3MgIFxuRC4gaHVuZ2FyaWNhIikgKw0KICBsYWJzKGNhcHRpb24gPSAgcGFzdGUwKCJQRVJNQU5PVkEgb24gY29uZGl0aW9uOiBwLXZhbHVlOiAiLCBwdikpICsgDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQ9IGVsZW1lbnRfcmVjdChmaWxsPSIjZjRmNGY0IiksDQogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplPTcpKSAtPiBwMg0KDQpnZ3Bsb3QocGNhX2RhdGEpICsNCiAgZ2VvbV9wb2ludChhZXMoeD1EaW0uMiwgeT1EaW0uMywgY29sb3VyPWNvbG9yKSwgc2l6ZT0zKSArDQogIHNjYWxlX2NvbG91cl9pZGVudGl0eSgiY29uZGl0aW9uIiwgbGFiZWxzPWMoIldOIiwgIlNEIiksIGd1aWRlID0gImxlZ2VuZCIpICsNCiAgZ2dyZXBlbDo6Z2VvbV90ZXh0X3JlcGVsKGFlcyh4PURpbS4yLCB5PURpbS4zLCBjb2xvdXI9Y29sb3IsIGxhYmVsPXNhbXBsZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVkZ2VfeSA9IC0yLCAgc2VlZCA9IDQyLCBzZWdtZW50LnNpemU9MC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIHhsYWIoRDJfdGV4dCkgKyANCiAgeWxhYihEM190ZXh0KSArDQogIGdndGl0bGUoIlBDQSBtZXRhdHJhbnNjcmlwdG9taWNzICBcbkQuIGh1bmdhcmljYSIpICsNCiAgbGFicyhjYXB0aW9uID0gIHBhc3RlMCgiUEVSTUFOT1ZBIG9uIGNvbmRpdGlvbjogcC12YWx1ZTogIiwgcHYpKSArIA0KICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kPSBlbGVtZW50X3JlY3QoZmlsbD0iI2Y0ZjRmNCIpLA0KICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZT03KSkgLT4gcDMNCg0KcGxvdGdyaWRfUENBIDwtIGdnYXJyYW5nZShwMSwgcDIsIHAzLCBsYWJlbHMgPSBjKCJBIiwgIkIiLCAiQyIpLCBjb21tb24ubGVnZW5kPVRSVUUsIGxlZ2VuZD0iYm90dG9tIiwgbnJvdz0xKSANCg0KcHJpbnQocGxvdGdyaWRfUENBKQ0KDQpnZ3NhdmUocGxvdCA9IHBsb3RncmlkX1BDQSwgZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9QQ0FfbWV0YXRyYW5zY3JpcHRvbWljc18zX2NvbXBvc2FudGVzX2Rpb2h1LnRpZmYiLCBkcGkgPSAzMDAsIHdpZHRoID0gMTUsIGhlaWdodCA9IDUsIGJnPSJ3aGl0ZSIpDQoNCmdnc2F2ZShwbG90PXAxLCBmaWxlbmFtZSA9ICIuLi9maWd1cmVzL1BDQV9tZXRhdHJhbnNjcmlwdG9taWNzX2Rpb2h1LnRpZmYiLCBkcGkgPSAzMDAsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNSwgYmc9IndoaXRlIikNCmBgYA0KDQpgYGB7ciAzRF9QQ0FfY2xyX2Rpb2h1LCB3ZWJnbD1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQ0KDQpyb3dfY29vcmQgPC0gcmVzX3BjYSRpbmQkY29vcmQNCg0KDQppbnZpc2libGUocmdsOjpvcGVuM2QoKSkNCg0KI3JnbDo6YmczZCgibGlnaHRncmF5IikNCnJnbDo6cGxvdDNkKHg9cm93X2Nvb3JkW2MoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksIDFdLCANCiAgICAgICAgICAgIHk9cm93X2Nvb3JkW2MoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksIDJdLCANCiAgICAgICAgICAgIHo9cm93X2Nvb3JkW2MoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksIDNdLA0KICAgICAgICAgICAgeGxhYiA9IHBhc3RlMChjb2xuYW1lcyhyb3dfY29vcmQpWzFdICwgIiAoIiAsIHN1YnN0cihhcy5jaGFyYWN0ZXIocmVzX3BjYSRlaWdbLDJdWzFdKSwgMSwgNSkgLCAiJSkiKSwNCiAgICAgICAgICAgIHlsYWIgPSBwYXN0ZTAoY29sbmFtZXMocm93X2Nvb3JkKVsyXSAsICIgKCIgLCBzdWJzdHIoYXMuY2hhcmFjdGVyKHJlc19wY2EkZWlnWywyXVsyXSksIDEsIDUpICwgIiUpIiksDQogICAgICAgICAgICB6bGFiID0gcGFzdGUwKGNvbG5hbWVzKHJvd19jb29yZClbM10gLCAiICgiICwgc3Vic3RyKGFzLmNoYXJhY3RlcihyZXNfcGNhJGVpZ1ssMl1bM10pLCAxLCA1KSAsICIlKSIpLA0KICAgICAgICAgICAgeGxpbSA9IGMobWluKHJvd19jb29yZFssIDFdKSwgbWF4KHJvd19jb29yZFssIDFdKSsxMCksIA0KICAgICAgICAgICAgeWxpbSA9IGMobWluKHJvd19jb29yZFssIDJdKSwgbWF4KHJvd19jb29yZFssIDJdKSsxMCksIA0KICAgICAgICAgICAgemxpbSA9IGMobWluKHJvd19jb29yZFssIDNdKSwgbWF4KHJvd19jb29yZFssIDNdKSsxMCksDQogICAgICAgICAgICBjb2wgPSAiZGFya2N5YW4iLA0KICAgICAgICAgICAgc2l6ZT0xMCwNCiAgICAgICAgICAgIG1haW4gPSAiUENBIEQuIGh1bmdhcmljYSIpDQoNCnJnbDo6dGV4dDNkKHg9cm93X2Nvb3JkW2MoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksIDFdKzUsIA0KICAgICAgICAgICAgeT1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgMl0rNSwgDQogICAgICAgICAgICB6PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAzXSs1LA0KICAgICAgICAgICAgdGV4dD1jKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLA0KICAgICAgICAgICAgY29sID0gImRhcmtjeWFuIiwNCiAgICAgICAgICAgIHNpemU9MTApDQoNCg0KcmdsOjpwb2ludHMzZCh4PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAxXSwgDQogICAgICAgICAgICAgIHk9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDJdLCANCiAgICAgICAgICAgICAgej1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgM10sDQogICAgICAgICAgICAgIGNvbCA9ICJkYXJrb3JhbmdlIiwNCiAgICAgICAgICAgICAgc2l6ZT0xMCkNCg0KcmdsOjp0ZXh0M2QoeD1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgMV0rNSwgDQogICAgICAgICAgICB5PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAyXSs1LCANCiAgICAgICAgICAgIHo9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDNdKzUsDQogICAgICAgICAgICB0ZXh0PWMoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksDQogICAgICAgICAgICBjb2wgPSAiZGFya29yYW5nZSIsDQogICAgICAgICAgICBzaXplPTEwKQ0KDQojIyBBY3RpdmF0ZSBmb3Igb3IgZ2lmIGdlbmVyYXRpb24NCiNwYXIzZCh3aW5kb3dSZWN0ID0gYygyMCwgMzAsIDgwMCwgODAwKSkNCg0KI3JnbDo6bW92aWUzZCgNCiMgIG1vdmllPSIzREFuaW1hdGVkX1BDQV9kaW9odSIsIA0KIyAgc3BpbjNkKCBheGlzID0gYygwLCAwLCAxKSwgcnBtID0gMyksDQojICBkdXJhdGlvbiA9IDIwLCANCiMgIGRpciA9ICIuLi9maWd1cmVzIiwNCiMgIHR5cGUgPSAiZ2lmIiwgDQojICBjbGVhbiA9IFRSVUUsIHdlYnNob3Q9RkFMU0UsIGZwcz0xMCkNCmBgYA0KDQojIyMjICpQc2V1ZG9tb25hcyBncmFtaW5pcyoNCg0KYGBge3IgUENBX2Nscl9wc2Vncn0NCg0KcmVzX3BjYSA8LSBQQ0EodChwc2Vncl9jbHIpLCBzY2FsZS51bml0ID0gVFJVRSwgZ3JhcGggPSBGQUxTRSkNCg0KYGBgDQoNCmBgYHtyIFBFUk1BTk9WQV9wc2Vncn0NCmNvdW50c19kYXRhIDwtIHQocHNlZ3JfY2xyKQ0KbWV0YWRhdGFfdG1wIDwtIGRhdGEuZnJhbWUobWV0YWRhdGFfdGFibGUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBUUlVFKQ0KcGVybWFub3ZhIDwtIGFkb25pczIoZm9ybXVsYSA9IGFzLmZvcm11bGEocGFzdGUwKCJjb3VudHNfZGF0YX4iLCAiY29uZGl0aW9uIikpLCANCiAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBtZXRhZGF0YV90bXAsIG1ldGhvZD0iZXVjbGlkZWFuIiwgIyBtZXRob2Q9ImJyYXkiLCAjb3R1X2RhdGF+VElNRQ0KICAgICAgICAgICAgICAgICAgICAgcGVybXV0YXRpb25zID0gOTk5LCBzcXJ0LmRpc3QgPSBGQUxTRSwgYWRkID0gRkFMU0UsIGJ5ID0gInRlcm1zIikNCnB2ID0gcGVybWFub3ZhJGBQcig+RilgWzFdDQojIHByaW50KHB2KQ0KDQpybShjb3VudHNfZGF0YSwgbWV0YWRhdGFfdG1wKQ0KYGBgDQoNCmBgYHtyIFBDQV8yRF9wbG90c19wc2VnciwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OX0NCg0KcGNhX3RtcCA8LSByYmluZChyZXNfcGNhJGluZCRjb29yZCwNCiAgICAgICAgICAgICAgICAgcmVzX3BjYSRpbmQuc3VwJGNvb3JkKSAlPiUgZGF0YS5mcmFtZSgpICU+JSANCiAgcm93bmFtZXNfdG9fY29sdW1uKCJzYW1wbGUiKQ0KDQoNCnBjYV9kYXRhIDwtIGxlZnRfam9pbihwY2FfdG1wLCByb3duYW1lc190b19jb2x1bW4obWV0YWRhdGFfdGFibGUpLCBieT1qb2luX2J5KCJzYW1wbGUiID09ICJyb3duYW1lIikpDQpybShwY2FfdG1wKQ0KDQpEMV90ZXh0ID0gcGFzdGUwKCJEaW0gMSAoIiwgDQogICAgICAgICAgICAgICAgIHJvdW5kKGRhdGEuZnJhbWUocmVzX3BjYSRlaWcpJHBlcmNlbnRhZ2Uub2YudmFyaWFuY2VbMV0sIGRpZ2l0cz0yKSwgDQogICAgICAgICAgICAgICAgICIlKSIpDQpEMl90ZXh0ID0gcGFzdGUwKCJEaW0gMiAoIiwgDQogICAgICAgICAgICAgICAgIHJvdW5kKGRhdGEuZnJhbWUocmVzX3BjYSRlaWcpJHBlcmNlbnRhZ2Uub2YudmFyaWFuY2VbMl0sIGRpZ2l0cz0yKSwgDQogICAgICAgICAgICAgICAgICIlKSIpDQpEM190ZXh0ID0gcGFzdGUwKCJEaW0gMyAoIiwgDQogICAgICAgICAgICAgICAgIHJvdW5kKGRhdGEuZnJhbWUocmVzX3BjYSRlaWcpJHBlcmNlbnRhZ2Uub2YudmFyaWFuY2VbM10sIGRpZ2l0cz0yKSwgDQogICAgICAgICAgICAgICAgICIlKSIpDQoNCmdncGxvdChwY2FfZGF0YSkgKw0KICBnZW9tX3BvaW50KGFlcyh4PURpbS4xLCB5PURpbS4yLCBjb2xvdXI9Y29sb3IsICksIHNpemU9MykgKw0KICBzY2FsZV9jb2xvdXJfaWRlbnRpdHkoImNvbmRpdGlvbiIsIGxhYmVscz1jKCJXTiIsICJTRCIpLCBndWlkZSA9ICJsZWdlbmQiKSArDQogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChhZXMoeD1EaW0uMSwgeT1EaW0uMiwgY29sb3VyPWNvbG9yLCBsYWJlbD1zYW1wbGUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG51ZGdlX3kgPSAtMiwgIHNlZWQgPSA0Miwgc2VnbWVudC5zaXplPTAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICB4bGFiKEQxX3RleHQpICsgDQogIHlsYWIoRDJfdGV4dCkgKw0KICBnZ3RpdGxlKCJQQ0EgbWV0YXRyYW5zY3JpcHRvbWljcyAgXG5QLiBncmFtaW5pcyIpICsNCiAgbGFicyhjYXB0aW9uID0gIHBhc3RlMCgiUEVSTUFOT1ZBIG9uIGNvbmRpdGlvbjogcC12YWx1ZTogIiwgcHYpKSArIA0KICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kPSBlbGVtZW50X3JlY3QoZmlsbD0iI2Y0ZjRmNCIpLA0KICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZT03KSkgLT4gcDENCiANCg0KZ2dwbG90KHBjYV9kYXRhKSArDQogIGdlb21fcG9pbnQoYWVzKHg9RGltLjEsIHk9RGltLjMsIGNvbG91cj1jb2xvciksIHNpemU9MykgKw0KICBzY2FsZV9jb2xvdXJfaWRlbnRpdHkoImNvbmRpdGlvbiIsIGxhYmVscz1jKCJXTiIsICJTRCIpLCBndWlkZSA9ICJsZWdlbmQiKSArDQogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChhZXMoeD1EaW0uMSwgeT1EaW0uMywgY29sb3VyPWNvbG9yLCBsYWJlbD1zYW1wbGUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG51ZGdlX3kgPSAtMiwgIHNlZWQgPSA0Miwgc2VnbWVudC5zaXplPTAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICB4bGFiKEQxX3RleHQpICsgDQogIHlsYWIoRDNfdGV4dCkgKw0KICBnZ3RpdGxlKCJQQ0EgbWV0YXRyYW5zY3JpcHRvbWljcyAgXG5QLiBncmFtaW5pcyIpICsNCiAgbGFicyhjYXB0aW9uID0gIHBhc3RlMCgiUEVSTUFOT1ZBIG9uIGNvbmRpdGlvbjogcC12YWx1ZTogIiwgcHYpKSArIA0KICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kPSBlbGVtZW50X3JlY3QoZmlsbD0iI2Y0ZjRmNCIpLA0KICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZT03KSkgLT4gcDINCg0KZ2dwbG90KHBjYV9kYXRhKSArDQogIGdlb21fcG9pbnQoYWVzKHg9RGltLjIsIHk9RGltLjMsIGNvbG91cj1jb2xvciksIHNpemU9MykgKw0KICBzY2FsZV9jb2xvdXJfaWRlbnRpdHkoImNvbmRpdGlvbiIsIGxhYmVscz1jKCJXTiIsICJTRCIpLCBndWlkZSA9ICJsZWdlbmQiKSArDQogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChhZXMoeD1EaW0uMiwgeT1EaW0uMywgY29sb3VyPWNvbG9yLCBsYWJlbD1zYW1wbGUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG51ZGdlX3kgPSAtMiwgIHNlZWQgPSA0Miwgc2VnbWVudC5zaXplPTAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICB4bGFiKEQyX3RleHQpICsgDQogIHlsYWIoRDNfdGV4dCkgKw0KICBnZ3RpdGxlKCJQQ0EgbWV0YXRyYW5zY3JpcHRvbWljcyAgXG5QLiBncmFtaW5pcyIpICsNCiAgbGFicyhjYXB0aW9uID0gIHBhc3RlMCgiUEVSTUFOT1ZBIG9uIGNvbmRpdGlvbjogcC12YWx1ZTogIiwgcHYpKSArIA0KICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kPSBlbGVtZW50X3JlY3QoZmlsbD0iI2Y0ZjRmNCIpLA0KICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZT03KSkgLT4gcDMNCg0KcGxvdGdyaWRfUENBIDwtIGdnYXJyYW5nZShwMSwgcDIsIHAzLCBsYWJlbHMgPSBjKCJBIiwgIkIiLCAiQyIpLCBjb21tb24ubGVnZW5kPVRSVUUsIGxlZ2VuZD0iYm90dG9tIiwgbnJvdz0xKSANCg0KcHJpbnQocGxvdGdyaWRfUENBKQ0KDQpnZ3NhdmUocGxvdCA9IHBsb3RncmlkX1BDQSwgZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9QQ0FfbWV0YXRyYW5zY3JpcHRvbWljc18zX2NvbXBvc2FudGVzX3BzZWdyLnRpZmYiLCBkcGkgPSAzMDAsIHdpZHRoID0gMTUsIGhlaWdodCA9IDUsIGJnPSJ3aGl0ZSIpDQoNCmdnc2F2ZShwbG90PXAxLCBmaWxlbmFtZSA9ICIuLi9maWd1cmVzL1BDQV9tZXRhdHJhbnNjcmlwdG9taWNzX3BzZWdyLnRpZmYiLCBkcGkgPSAzMDAsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNSwgYmc9IndoaXRlIikNCmBgYA0KDQpgYGB7ciAzRF9QQ0FfY2xyX3BzZWdyLCB3ZWJnbD1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQ0KDQpyb3dfY29vcmQgPC0gcmVzX3BjYSRpbmQkY29vcmQNCg0KaW52aXNpYmxlKHJnbDo6b3BlbjNkKCkpDQoNCiNyZ2w6OmJnM2QoImxpZ2h0Z3JheSIpDQpyZ2w6OnBsb3QzZCh4PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAxXSwgDQogICAgICAgICAgICB5PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAyXSwgDQogICAgICAgICAgICB6PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAzXSwNCiAgICAgICAgICAgIHhsYWIgPSBwYXN0ZTAoY29sbmFtZXMocm93X2Nvb3JkKVsxXSAsICIgKCIgLCBzdWJzdHIoYXMuY2hhcmFjdGVyKHJlc19wY2EkZWlnWywyXVsxXSksIDEsIDUpICwgIiUpIiksDQogICAgICAgICAgICB5bGFiID0gcGFzdGUwKGNvbG5hbWVzKHJvd19jb29yZClbMl0gLCAiICgiICwgc3Vic3RyKGFzLmNoYXJhY3RlcihyZXNfcGNhJGVpZ1ssMl1bMl0pLCAxLCA1KSAsICIlKSIpLA0KICAgICAgICAgICAgemxhYiA9IHBhc3RlMChjb2xuYW1lcyhyb3dfY29vcmQpWzNdICwgIiAoIiAsIHN1YnN0cihhcy5jaGFyYWN0ZXIocmVzX3BjYSRlaWdbLDJdWzNdKSwgMSwgNSkgLCAiJSkiKSwNCiAgICAgICAgICAgIHhsaW0gPSBjKG1pbihyb3dfY29vcmRbLCAxXSksIG1heChyb3dfY29vcmRbLCAxXSkrMTApLCANCiAgICAgICAgICAgIHlsaW0gPSBjKG1pbihyb3dfY29vcmRbLCAyXSksIG1heChyb3dfY29vcmRbLCAyXSkrMTApLCANCiAgICAgICAgICAgIHpsaW0gPSBjKG1pbihyb3dfY29vcmRbLCAzXSksIG1heChyb3dfY29vcmRbLCAzXSkrMTApLA0KICAgICAgICAgICAgY29sID0gImRhcmtjeWFuIiwNCiAgICAgICAgICAgIHNpemU9MTAsDQogICAgICAgICAgICBtYWluID0gIlBDQSBQLiBncmFtaW5pcyIpDQoNCnJnbDo6dGV4dDNkKHg9cm93X2Nvb3JkW2MoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksIDFdKzUsIA0KICAgICAgICAgICAgeT1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgMl0rNSwgDQogICAgICAgICAgICB6PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAzXSs1LA0KICAgICAgICAgICAgdGV4dD1jKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLA0KICAgICAgICAgICAgY29sID0gImRhcmtjeWFuIiwNCiAgICAgICAgICAgIHNpemU9MTApDQoNCg0KcmdsOjpwb2ludHMzZCh4PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAxXSwgDQogICAgICAgICAgICAgIHk9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDJdLCANCiAgICAgICAgICAgICAgej1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgM10sDQogICAgICAgICAgICAgIGNvbCA9ICJkYXJrb3JhbmdlIiwNCiAgICAgICAgICAgICAgc2l6ZT0xMCkNCg0KcmdsOjp0ZXh0M2QoeD1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgMV0rMywgDQogICAgICAgICAgICB5PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAyXSszLCANCiAgICAgICAgICAgIHo9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDNdKzMsDQogICAgICAgICAgICB0ZXh0PWMoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksDQogICAgICAgICAgICBjb2wgPSAiZGFya29yYW5nZSIsDQogICAgICAgICAgICBzaXplPTEwKQ0KDQojIyBBY3RpdmF0ZSBmb3Igb3IgZ2lmIGdlbmVyYXRpb24NCiNwYXIzZCh3aW5kb3dSZWN0ID0gYygyMCwgMzAsIDgwMCwgODAwKSkNCg0KI3JnbDo6bW92aWUzZCgNCiMgIG1vdmllPSIzREFuaW1hdGVkX1BDQV9wc2VnciIsIA0KIyAgc3BpbjNkKCBheGlzID0gYygwLCAwLCAxKSwgcnBtID0gMyksDQojICBkdXJhdGlvbiA9IDIwLCANCiMgIGRpciA9ICIuLi9maWd1cmVzIiwNCiMgIHR5cGUgPSAiZ2lmIiwgDQojICBjbGVhbiA9IFRSVUUsIHdlYnNob3Q9RkFMU0UsIGZwcz0xMCkNCmBgYA0KDQojIyMjICpQc2V1ZG9tb25hcyBzeXJpbmdhZSoNCg0KYGBge3IgUENBX2Nscl9wc2VzeX0NCg0KcmVzX3BjYSA8LSBQQ0EodChwc2VzeV9jbHIpLCBzY2FsZS51bml0ID0gVFJVRSwgZ3JhcGggPSBGQUxTRSkNCmBgYA0KDQpgYGB7ciBQRVJNQU5PVkFfcHNlc3l9DQpjb3VudHNfZGF0YSA8LSB0KHBzZXN5X2NscikNCm1ldGFkYXRhX3RtcCA8LSBkYXRhLmZyYW1lKG1ldGFkYXRhX3RhYmxlLCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkNCnBlcm1hbm92YSA8LSBhZG9uaXMyKGZvcm11bGEgPSBhcy5mb3JtdWxhKHBhc3RlMCgiY291bnRzX2RhdGF+IiwgImNvbmRpdGlvbiIpKSwgDQogICAgICAgICAgICAgICAgICAgICBkYXRhID0gbWV0YWRhdGFfdG1wLCBtZXRob2Q9ImV1Y2xpZGVhbiIsICMgbWV0aG9kPSJicmF5IiwgI290dV9kYXRhflRJTUUNCiAgICAgICAgICAgICAgICAgICAgIHBlcm11dGF0aW9ucyA9IDk5OSwgc3FydC5kaXN0ID0gRkFMU0UsIGFkZCA9IEZBTFNFLCBieSA9ICJ0ZXJtcyIpDQpwdiA9IHBlcm1hbm92YSRgUHIoPkYpYFsxXQ0KIyBwcmludChwdikNCg0Kcm0oY291bnRzX2RhdGEsIG1ldGFkYXRhX3RtcCkNCmBgYA0KDQpgYGB7ciBQQ0FfMkRfcGxvdHNfcHNlc3ksIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTl9DQoNCnBjYV90bXAgPC0gcmJpbmQocmVzX3BjYSRpbmQkY29vcmQsDQogICAgICAgICAgICAgICAgIHJlc19wY2EkaW5kLnN1cCRjb29yZCkgJT4lIGRhdGEuZnJhbWUoKSAlPiUgDQogIHJvd25hbWVzX3RvX2NvbHVtbigic2FtcGxlIikNCg0KDQpwY2FfZGF0YSA8LSBsZWZ0X2pvaW4ocGNhX3RtcCwgcm93bmFtZXNfdG9fY29sdW1uKG1ldGFkYXRhX3RhYmxlKSwgYnk9am9pbl9ieSgic2FtcGxlIiA9PSAicm93bmFtZSIpKQ0Kcm0ocGNhX3RtcCkNCg0KRDFfdGV4dCA9IHBhc3RlMCgiRGltIDEgKCIsIA0KICAgICAgICAgICAgICAgICByb3VuZChkYXRhLmZyYW1lKHJlc19wY2EkZWlnKSRwZXJjZW50YWdlLm9mLnZhcmlhbmNlWzFdLCBkaWdpdHM9MiksIA0KICAgICAgICAgICAgICAgICAiJSkiKQ0KRDJfdGV4dCA9IHBhc3RlMCgiRGltIDIgKCIsIA0KICAgICAgICAgICAgICAgICByb3VuZChkYXRhLmZyYW1lKHJlc19wY2EkZWlnKSRwZXJjZW50YWdlLm9mLnZhcmlhbmNlWzJdLCBkaWdpdHM9MiksIA0KICAgICAgICAgICAgICAgICAiJSkiKQ0KRDNfdGV4dCA9IHBhc3RlMCgiRGltIDMgKCIsIA0KICAgICAgICAgICAgICAgICByb3VuZChkYXRhLmZyYW1lKHJlc19wY2EkZWlnKSRwZXJjZW50YWdlLm9mLnZhcmlhbmNlWzNdLCBkaWdpdHM9MiksIA0KICAgICAgICAgICAgICAgICAiJSkiKQ0KDQpnZ3Bsb3QocGNhX2RhdGEpICsNCiAgZ2VvbV9wb2ludChhZXMoeD1EaW0uMSwgeT1EaW0uMiwgY29sb3VyPWNvbG9yLCApLCBzaXplPTMpICsNCiAgc2NhbGVfY29sb3VyX2lkZW50aXR5KCJjb25kaXRpb24iLCBsYWJlbHM9YygiV04iLCAiU0QiKSwgZ3VpZGUgPSAibGVnZW5kIikgKw0KICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoYWVzKHg9RGltLjEsIHk9RGltLjIsIGNvbG91cj1jb2xvciwgbGFiZWw9c2FtcGxlKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBudWRnZV95ID0gLTIsICBzZWVkID0gNDIsIHNlZ21lbnQuc2l6ZT0wLjEsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgeGxhYihEMV90ZXh0KSArIA0KICB5bGFiKEQyX3RleHQpICsNCiAgZ2d0aXRsZSgiUENBIG1ldGF0cmFuc2NyaXB0b21pY3MgIFxuUC4gc3lyaW5nYWUiKSArDQogIGxhYnMoY2FwdGlvbiA9ICBwYXN0ZTAoIlBFUk1BTk9WQSBvbiBjb25kaXRpb246IHAtdmFsdWU6ICIsIHB2KSkgKyANCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZD0gZWxlbWVudF9yZWN0KGZpbGw9IiNmNGY0ZjQiKSwNCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemU9NykpIC0+IHAxDQogDQoNCmdncGxvdChwY2FfZGF0YSkgKw0KICBnZW9tX3BvaW50KGFlcyh4PURpbS4xLCB5PURpbS4zLCBjb2xvdXI9Y29sb3IpLCBzaXplPTMpICsNCiAgc2NhbGVfY29sb3VyX2lkZW50aXR5KCJjb25kaXRpb24iLCBsYWJlbHM9YygiV04iLCAiU0QiKSwgZ3VpZGUgPSAibGVnZW5kIikgKw0KICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoYWVzKHg9RGltLjEsIHk9RGltLjMsIGNvbG91cj1jb2xvciwgbGFiZWw9c2FtcGxlKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBudWRnZV95ID0gLTIsICBzZWVkID0gNDIsIHNlZ21lbnQuc2l6ZT0wLjEsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgeGxhYihEMV90ZXh0KSArIA0KICB5bGFiKEQzX3RleHQpICsNCiAgZ2d0aXRsZSgiUENBIG1ldGF0cmFuc2NyaXB0b21pY3MgIFxuUC4gc3lyaW5nYWUiKSArDQogIGxhYnMoY2FwdGlvbiA9ICBwYXN0ZTAoIlBFUk1BTk9WQSBvbiBjb25kaXRpb246IHAtdmFsdWU6ICIsIHB2KSkgKyANCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZD0gZWxlbWVudF9yZWN0KGZpbGw9IiNmNGY0ZjQiKSwNCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemU9NykpIC0+IHAyDQoNCmdncGxvdChwY2FfZGF0YSkgKw0KICBnZW9tX3BvaW50KGFlcyh4PURpbS4yLCB5PURpbS4zLCBjb2xvdXI9Y29sb3IpLCBzaXplPTMpICsNCiAgc2NhbGVfY29sb3VyX2lkZW50aXR5KCJjb25kaXRpb24iLCBsYWJlbHM9YygiV04iLCAiU0QiKSwgZ3VpZGUgPSAibGVnZW5kIikgKw0KICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoYWVzKHg9RGltLjIsIHk9RGltLjMsIGNvbG91cj1jb2xvciwgbGFiZWw9c2FtcGxlKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBudWRnZV95ID0gLTIsICBzZWVkID0gNDIsIHNlZ21lbnQuc2l6ZT0wLjEsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgeGxhYihEMl90ZXh0KSArIA0KICB5bGFiKEQzX3RleHQpICsNCiAgZ2d0aXRsZSgiUENBIG1ldGF0cmFuc2NyaXB0b21pY3MgIFxuUC4gc3lyaW5nYWUiKSArDQogIGxhYnMoY2FwdGlvbiA9ICBwYXN0ZTAoIlBFUk1BTk9WQSBvbiBjb25kaXRpb246IHAtdmFsdWU6ICIsIHB2KSkgKyANCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZD0gZWxlbWVudF9yZWN0KGZpbGw9IiNmNGY0ZjQiKSwNCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemU9NykpIC0+IHAzDQoNCnBsb3RncmlkX1BDQSA8LSBnZ2FycmFuZ2UocDEsIHAyLCBwMywgbGFiZWxzID0gYygiQSIsICJCIiwgIkMiKSwgY29tbW9uLmxlZ2VuZD1UUlVFLCBsZWdlbmQ9ImJvdHRvbSIsIG5yb3c9MSkgDQoNCnByaW50KHBsb3RncmlkX1BDQSkNCg0KZ2dzYXZlKHBsb3QgPSBwbG90Z3JpZF9QQ0EsIGZpbGVuYW1lID0gIi4uL2ZpZ3VyZXMvUENBX21ldGF0cmFuc2NyaXB0b21pY3NfM19jb21wb3NhbnRlc19wc2VzeS50aWZmIiwgZHBpID0gMzAwLCB3aWR0aCA9IDE1LCBoZWlnaHQgPSA1LCBiZz0id2hpdGUiKQ0KDQpnZ3NhdmUocGxvdD1wMSwgZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9QQ0FfbWV0YXRyYW5zY3JpcHRvbWljc19wc2VzeS50aWZmIiwgZHBpID0gMzAwLCB3aWR0aCA9IDYsIGhlaWdodCA9IDUsIGJnPSJ3aGl0ZSIpDQpgYGANCg0KYGBge3IgM0RfUENBX2Nscl9wc2VzeSwgd2ViZ2w9VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9N30NCg0Kcm93X2Nvb3JkIDwtIHJlc19wY2EkaW5kJGNvb3JkDQoNCmludmlzaWJsZShyZ2w6Om9wZW4zZCgpKQ0KDQojcmdsOjpiZzNkKCJsaWdodGdyYXkiKQ0KcmdsOjpwbG90M2QoeD1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgMV0sIA0KICAgICAgICAgICAgeT1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgMl0sIA0KICAgICAgICAgICAgej1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgM10sDQogICAgICAgICAgICB4bGFiID0gcGFzdGUwKGNvbG5hbWVzKHJvd19jb29yZClbMV0gLCAiICgiICwgc3Vic3RyKGFzLmNoYXJhY3RlcihyZXNfcGNhJGVpZ1ssMl1bMV0pLCAxLCA1KSAsICIlKSIpLA0KICAgICAgICAgICAgeWxhYiA9IHBhc3RlMChjb2xuYW1lcyhyb3dfY29vcmQpWzJdICwgIiAoIiAsIHN1YnN0cihhcy5jaGFyYWN0ZXIocmVzX3BjYSRlaWdbLDJdWzJdKSwgMSwgNSkgLCAiJSkiKSwNCiAgICAgICAgICAgIHpsYWIgPSBwYXN0ZTAoY29sbmFtZXMocm93X2Nvb3JkKVszXSAsICIgKCIgLCBzdWJzdHIoYXMuY2hhcmFjdGVyKHJlc19wY2EkZWlnWywyXVszXSksIDEsIDUpICwgIiUpIiksDQogICAgICAgICAgICB4bGltID0gYyhtaW4ocm93X2Nvb3JkWywgMV0pLCBtYXgocm93X2Nvb3JkWywgMV0pKzEwKSwgDQogICAgICAgICAgICB5bGltID0gYyhtaW4ocm93X2Nvb3JkWywgMl0pLCBtYXgocm93X2Nvb3JkWywgMl0pKzEwKSwgDQogICAgICAgICAgICB6bGltID0gYyhtaW4ocm93X2Nvb3JkWywgM10pLCBtYXgocm93X2Nvb3JkWywgM10pKzEwKSwNCiAgICAgICAgICAgIGNvbCA9ICJkYXJrY3lhbiIsDQogICAgICAgICAgICBzaXplPTEwLA0KICAgICAgICAgICAgbWFpbiA9ICJQQ0EgUC4gc3lyaW5nYWUiKQ0KDQpyZ2w6OnRleHQzZCh4PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAxXSszLCANCiAgICAgICAgICAgIHk9cm93X2Nvb3JkW2MoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksIDJdKzMsIA0KICAgICAgICAgICAgej1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgM10rMywNCiAgICAgICAgICAgIHRleHQ9YygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwNCiAgICAgICAgICAgIGNvbCA9ICJkYXJrY3lhbiIsDQogICAgICAgICAgICBzaXplPTEwKQ0KDQoNCnJnbDo6cG9pbnRzM2QoeD1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgMV0sIA0KICAgICAgICAgICAgICB5PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAyXSwgDQogICAgICAgICAgICAgIHo9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDNdLA0KICAgICAgICAgICAgICBjb2wgPSAiZGFya29yYW5nZSIsDQogICAgICAgICAgICAgIHNpemU9MTApDQoNCnJnbDo6dGV4dDNkKHg9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDFdKzMsIA0KICAgICAgICAgICAgeT1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgMl0rMywgDQogICAgICAgICAgICB6PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAzXSszLA0KICAgICAgICAgICAgdGV4dD1jKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLA0KICAgICAgICAgICAgY29sID0gImRhcmtvcmFuZ2UiLA0KICAgICAgICAgICAgc2l6ZT0xMCkNCg0KDQojIyBBY3RpdmF0ZSBmb3Igb3IgZ2lmIGdlbmVyYXRpb24NCiNwYXIzZCh3aW5kb3dSZWN0ID0gYygyMCwgMzAsIDgwMCwgODAwKSkNCg0KI3JnbDo6bW92aWUzZCgNCiMgIG1vdmllPSIzREFuaW1hdGVkX1BDQV9wc2VzeSIsIA0KIyAgc3BpbjNkKCBheGlzID0gYygwLCAwLCAxKSwgcnBtID0gMyksDQojICBkdXJhdGlvbiA9IDIwLCANCiMgIGRpciA9ICIuLi9maWd1cmVzIiwNCiMgIHR5cGUgPSAiZ2lmIiwgDQojICBjbGVhbiA9IFRSVUUsIHdlYnNob3Q9RkFMU0UsIGZwcz0xMCkNCmBgYA0KDQojIyMjICpSaG9kb2NvY2N1cyBlbmNsZW5zaXMqDQoNCmBgYHtyIFBDQV9jbHJfcmhvZW59DQoNCnJlc19wY2EgPC0gUENBKHQocmhvZW5fY2xyKSwgc2NhbGUudW5pdCA9IFRSVUUsIGdyYXBoID0gRkFMU0UpDQpgYGANCg0KDQpgYGB7ciBQRVJNQU5PVkFfcmhvZW59DQpjb3VudHNfZGF0YSA8LSB0KHJob2VuX2NscikNCm1ldGFkYXRhX3RtcCA8LSBkYXRhLmZyYW1lKG1ldGFkYXRhX3RhYmxlLCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkNCnBlcm1hbm92YSA8LSBhZG9uaXMyKGZvcm11bGEgPSBhcy5mb3JtdWxhKHBhc3RlMCgiY291bnRzX2RhdGF+IiwgImNvbmRpdGlvbiIpKSwgDQogICAgICAgICAgICAgICAgICAgICBkYXRhID0gbWV0YWRhdGFfdG1wLCBtZXRob2Q9ImV1Y2xpZGVhbiIsICMgbWV0aG9kPSJicmF5IiwgI290dV9kYXRhflRJTUUNCiAgICAgICAgICAgICAgICAgICAgIHBlcm11dGF0aW9ucyA9IDk5OSwgc3FydC5kaXN0ID0gRkFMU0UsIGFkZCA9IEZBTFNFLCBieSA9ICJ0ZXJtcyIpDQpwdiA9IHBlcm1hbm92YSRgUHIoPkYpYFsxXQ0KIyBwcmludChwdikNCg0Kcm0oY291bnRzX2RhdGEsIG1ldGFkYXRhX3RtcCkNCmBgYA0KDQpgYGB7ciBQQ0FfMkRfcGxvdHNfcmhvZW4sIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTl9DQoNCnBjYV90bXAgPC0gcmJpbmQocmVzX3BjYSRpbmQkY29vcmQsDQogICAgICAgICAgICAgICAgIHJlc19wY2EkaW5kLnN1cCRjb29yZCkgJT4lIGRhdGEuZnJhbWUoKSAlPiUgDQogIHJvd25hbWVzX3RvX2NvbHVtbigic2FtcGxlIikNCg0KDQpwY2FfZGF0YSA8LSBsZWZ0X2pvaW4ocGNhX3RtcCwgcm93bmFtZXNfdG9fY29sdW1uKG1ldGFkYXRhX3RhYmxlKSwgYnk9am9pbl9ieSgic2FtcGxlIiA9PSAicm93bmFtZSIpKQ0Kcm0ocGNhX3RtcCkNCg0KRDFfdGV4dCA9IHBhc3RlMCgiRGltIDEgKCIsIA0KICAgICAgICAgICAgICAgICByb3VuZChkYXRhLmZyYW1lKHJlc19wY2EkZWlnKSRwZXJjZW50YWdlLm9mLnZhcmlhbmNlWzFdLCBkaWdpdHM9MiksIA0KICAgICAgICAgICAgICAgICAiJSkiKQ0KRDJfdGV4dCA9IHBhc3RlMCgiRGltIDIgKCIsIA0KICAgICAgICAgICAgICAgICByb3VuZChkYXRhLmZyYW1lKHJlc19wY2EkZWlnKSRwZXJjZW50YWdlLm9mLnZhcmlhbmNlWzJdLCBkaWdpdHM9MiksIA0KICAgICAgICAgICAgICAgICAiJSkiKQ0KRDNfdGV4dCA9IHBhc3RlMCgiRGltIDMgKCIsIA0KICAgICAgICAgICAgICAgICByb3VuZChkYXRhLmZyYW1lKHJlc19wY2EkZWlnKSRwZXJjZW50YWdlLm9mLnZhcmlhbmNlWzNdLCBkaWdpdHM9MiksIA0KICAgICAgICAgICAgICAgICAiJSkiKQ0KDQpnZ3Bsb3QocGNhX2RhdGEpICsNCiAgZ2VvbV9wb2ludChhZXMoeD1EaW0uMSwgeT1EaW0uMiwgY29sb3VyPWNvbG9yLCApLCBzaXplPTMpICsNCiAgc2NhbGVfY29sb3VyX2lkZW50aXR5KCJjb25kaXRpb24iLCBsYWJlbHM9YygiV04iLCAiU0QiKSwgZ3VpZGUgPSAibGVnZW5kIikgKw0KICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoYWVzKHg9RGltLjEsIHk9RGltLjIsIGNvbG91cj1jb2xvciwgbGFiZWw9c2FtcGxlKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBudWRnZV95ID0gLTIsICBzZWVkID0gNDIsIHNlZ21lbnQuc2l6ZT0wLjEsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgeGxhYihEMV90ZXh0KSArIA0KICB5bGFiKEQyX3RleHQpICsNCiAgZ2d0aXRsZSgiUENBIG1ldGF0cmFuc2NyaXB0b21pY3MgIFxuUi4gZW5jbGVuc2lzIikgKw0KICBsYWJzKGNhcHRpb24gPSAgcGFzdGUwKCJQRVJNQU5PVkEgb24gY29uZGl0aW9uOiBwLXZhbHVlOiAiLCBwdikpICsgDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQ9IGVsZW1lbnRfcmVjdChmaWxsPSIjZjRmNGY0IiksDQogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplPTcpKSAtPiBwMQ0KIA0KDQpnZ3Bsb3QocGNhX2RhdGEpICsNCiAgZ2VvbV9wb2ludChhZXMoeD1EaW0uMSwgeT1EaW0uMywgY29sb3VyPWNvbG9yKSwgc2l6ZT0zKSArDQogIHNjYWxlX2NvbG91cl9pZGVudGl0eSgiY29uZGl0aW9uIiwgbGFiZWxzPWMoIldOIiwgIlNEIiksIGd1aWRlID0gImxlZ2VuZCIpICsNCiAgZ2dyZXBlbDo6Z2VvbV90ZXh0X3JlcGVsKGFlcyh4PURpbS4xLCB5PURpbS4zLCBjb2xvdXI9Y29sb3IsIGxhYmVsPXNhbXBsZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVkZ2VfeSA9IC0yLCAgc2VlZCA9IDQyLCBzZWdtZW50LnNpemU9MC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIHhsYWIoRDFfdGV4dCkgKyANCiAgeWxhYihEM190ZXh0KSArDQogIGdndGl0bGUoIlBDQSBtZXRhdHJhbnNjcmlwdG9taWNzICBcblIuIGVuY2xlbnNpcyIpICsNCiAgbGFicyhjYXB0aW9uID0gIHBhc3RlMCgiUEVSTUFOT1ZBIG9uIGNvbmRpdGlvbjogcC12YWx1ZTogIiwgcHYpKSArIA0KICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kPSBlbGVtZW50X3JlY3QoZmlsbD0iI2Y0ZjRmNCIpLA0KICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZT03KSkgLT4gcDINCg0KZ2dwbG90KHBjYV9kYXRhKSArDQogIGdlb21fcG9pbnQoYWVzKHg9RGltLjIsIHk9RGltLjMsIGNvbG91cj1jb2xvciksIHNpemU9MykgKw0KICBzY2FsZV9jb2xvdXJfaWRlbnRpdHkoImNvbmRpdGlvbiIsIGxhYmVscz1jKCJXTiIsICJTRCIpLCBndWlkZSA9ICJsZWdlbmQiKSArDQogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChhZXMoeD1EaW0uMiwgeT1EaW0uMywgY29sb3VyPWNvbG9yLCBsYWJlbD1zYW1wbGUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG51ZGdlX3kgPSAtMiwgIHNlZWQgPSA0Miwgc2VnbWVudC5zaXplPTAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICB4bGFiKEQyX3RleHQpICsgDQogIHlsYWIoRDNfdGV4dCkgKw0KICBnZ3RpdGxlKCJQQ0EgbWV0YXRyYW5zY3JpcHRvbWljcyAgXG5SLiBlbmNsZW5zaXMiKSArDQogIGxhYnMoY2FwdGlvbiA9ICBwYXN0ZTAoIlBFUk1BTk9WQSBvbiBjb25kaXRpb246IHAtdmFsdWU6ICIsIHB2KSkgKyANCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZD0gZWxlbWVudF9yZWN0KGZpbGw9IiNmNGY0ZjQiKSwNCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemU9NykpIC0+IHAzDQoNCnBsb3RncmlkX1BDQSA8LSBnZ2FycmFuZ2UocDEsIHAyLCBwMywgbGFiZWxzID0gYygiQSIsICJCIiwgIkMiKSwgY29tbW9uLmxlZ2VuZD1UUlVFLCBsZWdlbmQ9ImJvdHRvbSIsIG5yb3c9MSkgDQoNCnByaW50KHBsb3RncmlkX1BDQSkNCg0KZ2dzYXZlKHBsb3QgPSBwbG90Z3JpZF9QQ0EsIGZpbGVuYW1lID0gIi4uL2ZpZ3VyZXMvUENBX21ldGF0cmFuc2NyaXB0b21pY3NfM19jb21wb3NhbnRlc19yaG9lbi50aWZmIiwgZHBpID0gMzAwLCB3aWR0aCA9IDE1LCBoZWlnaHQgPSA1LCBiZz0id2hpdGUiKQ0KDQpnZ3NhdmUocGxvdD1wMSwgZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9QQ0FfbWV0YXRyYW5zY3JpcHRvbWljc19yaG9lbi50aWZmIiwgZHBpID0gMzAwLCB3aWR0aCA9IDYsIGhlaWdodCA9IDUsIGJnPSJ3aGl0ZSIpDQpgYGANCg0KYGBge3IgM0RfUENBX2Nscl9yaG9lbiwgd2ViZ2w9VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9N30NCg0Kcm93X2Nvb3JkIDwtIHJlc19wY2EkaW5kJGNvb3JkDQoNCmludmlzaWJsZShyZ2w6Om9wZW4zZCgpKQ0KDQojcmdsOjpiZzNkKCJsaWdodGdyYXkiKQ0KcmdsOjpwbG90M2QoeD1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgMV0sIA0KICAgICAgICAgICAgeT1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgMl0sIA0KICAgICAgICAgICAgej1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgM10sDQogICAgICAgICAgICB4bGFiID0gcGFzdGUwKGNvbG5hbWVzKHJvd19jb29yZClbMV0gLCAiICgiICwgc3Vic3RyKGFzLmNoYXJhY3RlcihyZXNfcGNhJGVpZ1ssMl1bMV0pLCAxLCA1KSAsICIlKSIpLA0KICAgICAgICAgICAgeWxhYiA9IHBhc3RlMChjb2xuYW1lcyhyb3dfY29vcmQpWzJdICwgIiAoIiAsIHN1YnN0cihhcy5jaGFyYWN0ZXIocmVzX3BjYSRlaWdbLDJdWzJdKSwgMSwgNSkgLCAiJSkiKSwNCiAgICAgICAgICAgIHpsYWIgPSBwYXN0ZTAoY29sbmFtZXMocm93X2Nvb3JkKVszXSAsICIgKCIgLCBzdWJzdHIoYXMuY2hhcmFjdGVyKHJlc19wY2EkZWlnWywyXVszXSksIDEsIDUpICwgIiUpIiksDQogICAgICAgICAgICB4bGltID0gYyhtaW4ocm93X2Nvb3JkWywgMV0pLCBtYXgocm93X2Nvb3JkWywgMV0pKzEwKSwgDQogICAgICAgICAgICB5bGltID0gYyhtaW4ocm93X2Nvb3JkWywgMl0pLCBtYXgocm93X2Nvb3JkWywgMl0pKzEwKSwgDQogICAgICAgICAgICB6bGltID0gYyhtaW4ocm93X2Nvb3JkWywgM10pLCBtYXgocm93X2Nvb3JkWywgM10pKzEwKSwNCiAgICAgICAgICAgIGNvbCA9ICJkYXJrY3lhbiIsDQogICAgICAgICAgICBzaXplPTEwLA0KICAgICAgICAgICAgbWFpbiA9ICJQQ0EgUi4gZW5jbGVuc2lzIikNCg0KcmdsOjp0ZXh0M2QoeD1yb3dfY29vcmRbYygiV05fVEZfMSIsICJXTl9URl8yIiwgIldOX1RGXzMiKSwgMV0rMywgDQogICAgICAgICAgICB5PXJvd19jb29yZFtjKCJXTl9URl8xIiwgIldOX1RGXzIiLCAiV05fVEZfMyIpLCAyXSszLCANCiAgICAgICAgICAgIHo9cm93X2Nvb3JkW2MoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksIDNdKzMsDQogICAgICAgICAgICB0ZXh0PWMoIldOX1RGXzEiLCAiV05fVEZfMiIsICJXTl9URl8zIiksDQogICAgICAgICAgICBjb2wgPSAiZGFya2N5YW4iLA0KICAgICAgICAgICAgc2l6ZT0xMCkNCg0KDQpyZ2w6OnBvaW50czNkKHg9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDFdLCANCiAgICAgICAgICAgICAgeT1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgMl0sIA0KICAgICAgICAgICAgICB6PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAzXSwNCiAgICAgICAgICAgICAgY29sID0gImRhcmtvcmFuZ2UiLA0KICAgICAgICAgICAgICBzaXplPTEwKQ0KDQpyZ2w6OnRleHQzZCh4PXJvd19jb29yZFtjKCJTRF9URl8xIiwgIlNEX1RGXzIiLCAiU0RfVEZfMyIpLCAxXSszLCANCiAgICAgICAgICAgIHk9cm93X2Nvb3JkW2MoIlNEX1RGXzEiLCAiU0RfVEZfMiIsICJTRF9URl8zIiksIDJdKzMsIA0KICAgICAgICAgICAgej1yb3dfY29vcmRbYygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwgM10rMywNCiAgICAgICAgICAgIHRleHQ9YygiU0RfVEZfMSIsICJTRF9URl8yIiwgIlNEX1RGXzMiKSwNCiAgICAgICAgICAgIGNvbCA9ICJkYXJrb3JhbmdlIiwNCiAgICAgICAgICAgIHNpemU9MTApDQoNCg0KIyMgQWN0aXZhdGUgZm9yIG9yIGdpZiBnZW5lcmF0aW9uDQojcGFyM2Qod2luZG93UmVjdCA9IGMoMjAsIDMwLCA4MDAsIDgwMCkpDQoNCiNyZ2w6Om1vdmllM2QoDQojICBtb3ZpZT0iM0RBbmltYXRlZF9QQ0FfcmhvZW4iLCANCiMgIHNwaW4zZCggYXhpcyA9IGMoMCwgMCwgMSksIHJwbSA9IDMpLA0KIyAgZHVyYXRpb24gPSAyMCwgDQojICBkaXIgPSAiLi4vZmlndXJlcyIsDQojICB0eXBlID0gImdpZiIsIA0KIyAgY2xlYW4gPSBUUlVFLCB3ZWJzaG90PUZBTFNFLCBmcHM9MTApDQpgYGANCg0KDQojIyMgU2FtcGxlcyBoaWVyYXJjaGljYWwgY2x1c3RlcmluZyBieSBzcGVjaWVzIHsudGFic2V0fQ0KIyMjIyAqRGlvc3plZ2lhIGh1bmdhcmljYSoNCg0KYGBge3IgZGlzdGFuY2VfbWF0cmljZXNfZGlvaHV9DQojIyMjIFNhbXBsZSBkaXN0YW5jZXMgIyMjIw0KbWVzc2FnZSgiQ29tcHV0aW5nIGludGVyLXNhbXBsZSBkaXN0YW5jZXMiKQ0KDQojIyBQZWFyc29uDQpkaXN0X3BlYXJzb25fZGlvaHUgPC0gYXMuZGlzdCgxIC0gY29yKGRpb2h1X2NsciwgdXNlID0gImV2ZXJ5dGhpbmciLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInBlYXJzb24iKSkNCmBgYA0KDQpgYGB7ciBzYW1wbGVfdHJlZV9kaW9odX0NCm1lc3NhZ2UoIlNhbXBsZSBjbHVzdGVyaW5nIikNCg0KdHJlZV9wZWFyc29uX2Rpb2h1IDwtIGhjbHVzdChkaXN0X3BlYXJzb25fZGlvaHUsIG1ldGhvZCA9ICJjb21wbGV0ZSIpDQoNCmBgYA0KDQpgYGB7ciBwZWFyc29uX3RyZWVfZGlvaHUsIGZpZy5oZWlnaHQ9N30NCnBhcihiZyA9ICJ3aGl0ZSIsIG1mcm93PWMoMSwgMSkpDQpwbG90Q29sb3JlZENsdXN0ZXJzKHRyZWVfcGVhcnNvbl9kaW9odSwgbGFicyA9IHJvdy5uYW1lcyhtZXRhZGF0YV90YWJsZSksDQogICAgICAgICAgICAgICAgICAgIHlsYWIgPSBOQSwgeGxhYiA9IE5BLCBjZXggPSAxLCBsYXMgPSAxLA0KICAgICAgICAgICAgICAgICAgICBjb2xzID0gbWV0YWRhdGFfdGFibGUkY29sb3IsIGNvbCA9ICJibGFjayIsDQogICAgICAgICAgICAgICAgICAgIG1haW4gPSAiU2FtcGxlcyBQZWFyc29uIGRpc3RhbmNlIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nLA0KY29tcGxldGUgbGlua2FnZSwgRC4gaHVuZ2FyaWNhIGdlbmVzLiIpDQpgYGANCg0KTmF0dXJhbCBzZXBhcmF0aW9uIG9mIHNhbXBsZXMgYWNjb3JkaW5nIHRvIHRoZWlyIGluY3ViYXRpb24gY29uZGl0aW9uIGZvciAqRC4gaHVuZ2FyaWNhKi4NCg0KIyMjIyAqUHNldWRvbW9uYXMgZ3JhbWluaXMqDQoNCmBgYHtyIGRpc3RhbmNlX21hdHJpY2VzX3BzZWdyfQ0KIyMjIyBTYW1wbGUgZGlzdGFuY2VzICMjIyMNCm1lc3NhZ2UoIkNvbXB1dGluZyBpbnRlci1zYW1wbGUgZGlzdGFuY2VzIikNCg0KIyMgUGVhcnNvbg0KZGlzdF9wZWFyc29uX3BzZWdyIDwtIGFzLmRpc3QoMSAtIGNvcihwc2Vncl9jbHIsIHVzZSA9ICJldmVyeXRoaW5nIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJwZWFyc29uIikpDQpgYGANCg0KYGBge3Igc2FtcGxlX3RyZWVfcHNlZ3J9DQptZXNzYWdlKCJTYW1wbGUgY2x1c3RlcmluZyIpDQoNCnRyZWVfcGVhcnNvbl9wc2VnciA8LSBoY2x1c3QoZGlzdF9wZWFyc29uX3BzZWdyLCBtZXRob2QgPSAiY29tcGxldGUiKQ0KYGBgDQoNCg0KYGBge3IgcGVhcnNvbl90cmVlX3BzZWdyLCBmaWcuaGVpZ2h0PTd9DQpwYXIoYmcgPSAid2hpdGUiLCBtZnJvdz1jKDEsIDEpKQ0KcGxvdENvbG9yZWRDbHVzdGVycyh0cmVlX3BlYXJzb25fcHNlZ3IsIGxhYnMgPSByb3cubmFtZXMobWV0YWRhdGFfdGFibGUpLA0KICAgICAgICAgICAgICAgICAgICB5bGFiID0gTkEsIHhsYWIgPSBOQSwgY2V4ID0gMSwgbGFzID0gMSwNCiAgICAgICAgICAgICAgICAgICAgY29scyA9IG1ldGFkYXRhX3RhYmxlJGNvbG9yLCBjb2wgPSAiYmxhY2siLA0KICAgICAgICAgICAgICAgICAgICBtYWluID0gIlNhbXBsZXMgUGVhcnNvbiBkaXN0YW5jZSBoaWVyYXJjaGljYWwgY2x1c3RlcmluZywNCmNvbXBsZXRlIGxpbmthZ2UsIFAuIGdyYW1pbmlzIGdlbmVzLiIpDQpgYGANCg0KRm9yICpQLiBncmFtaW5pcyosIHRoZSBjbHVzdGVyaW5nIGRvZXMgbm90IGRpc3Rpbmd1aXNoIGJldHdlZW4gdGhlIHR3byBpbmN1YmF0aW9uIGNvbmRpdGlvbnMsIHByb2JhYmx5IGJlY2F1c2Ugb2YgdGhlIHZlcnkgbG93IGFtb3VudHMgb2YgY291bnRzIGF0dHJpYnV0ZWQgdG8gdGhpcyBzcGVjaWVzLg0KDQoNCiMjIyMgKlBzZXVkb21vbmFzIHN5cmluZ2FlKg0KDQpgYGB7ciBkaXN0YW5jZV9tYXRyaWNlc19wc2VzeX0NCiMjIyMgU2FtcGxlIGRpc3RhbmNlcyAjIyMjDQptZXNzYWdlKCJDb21wdXRpbmcgaW50ZXItc2FtcGxlIGRpc3RhbmNlcyIpDQoNCiMjIFBlYXJzb24NCmRpc3RfcGVhcnNvbl9wc2VzeSA8LSBhcy5kaXN0KDEgLSBjb3IocHNlc3lfY2xyLCB1c2UgPSAiZXZlcnl0aGluZyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAicGVhcnNvbiIpKQ0KYGBgDQoNCmBgYHtyIHNhbXBsZV90cmVlX3BzZXN5fQ0KbWVzc2FnZSgiU2FtcGxlIGNsdXN0ZXJpbmciKQ0KDQp0cmVlX3BlYXJzb25fcHNlc3kgPC0gaGNsdXN0KGRpc3RfcGVhcnNvbl9wc2VzeSwgbWV0aG9kID0gImNvbXBsZXRlIikNCmBgYA0KDQpgYGB7ciBwZWFyc29uX3RyZWVfcHNlc3ksIGZpZy5oZWlnaHQ9N30NCnBhcihiZyA9ICJ3aGl0ZSIsIG1mcm93PWMoMSwgMSkpDQpwbG90Q29sb3JlZENsdXN0ZXJzKHRyZWVfcGVhcnNvbl9wc2VzeSwgbGFicyA9IHJvdy5uYW1lcyhtZXRhZGF0YV90YWJsZSksDQogICAgICAgICAgICAgICAgICAgIHlsYWIgPSBOQSwgeGxhYiA9IE5BLCBjZXggPSAxLCBsYXMgPSAxLA0KICAgICAgICAgICAgICAgICAgICBjb2xzID0gbWV0YWRhdGFfdGFibGUkY29sb3IsIGNvbCA9ICJibGFjayIsDQogICAgICAgICAgICAgICAgICAgIG1haW4gPSAiU2FtcGxlcyBQZWFyc29uIGRpc3RhbmNlIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nLA0KY29tcGxldGUgbGlua2FnZSwgUC4gc3lyaW5nYWUgZ2VuZXMuIikNCmBgYA0KDQpTYW1wbGVzIGFyZSBzZXBhcmF0ZWQgYWNjb3JkaW5nIHRvIHRoZWlyIGV4cGVyaW1lbnRhbCBjb25kaXRpb24sIHdoaWNoIGlzIGVuY291cmFnaW5nIGZvciBmdXJ0aGVyIGFuYWx5c2lzIG9mICpQLiBzeXJpbmdhZSouDQoNCg0KDQojIyMjICpSaG9kb2NvY2N1cyBlbmNsZW5zaXMqDQoNCmBgYHtyIGRpc3RhbmNlX21hdHJpY2VzX3Job2VufQ0KIyMjIyBTYW1wbGUgZGlzdGFuY2VzICMjIyMNCm1lc3NhZ2UoIkNvbXB1dGluZyBpbnRlci1zYW1wbGUgZGlzdGFuY2VzIikNCg0KIyMgUGVhcnNvbg0KZGlzdF9wZWFyc29uX3Job2VuIDwtIGFzLmRpc3QoMSAtIGNvcihyaG9lbl9jbHIsIHVzZSA9ICJldmVyeXRoaW5nIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJwZWFyc29uIikpDQpgYGANCg0KYGBge3Igc2FtcGxlX3RyZWVfcmhvZW59DQptZXNzYWdlKCJTYW1wbGUgY2x1c3RlcmluZyIpDQoNCnRyZWVfcGVhcnNvbl9yaG9lbiA8LSBoY2x1c3QoZGlzdF9wZWFyc29uX3Job2VuLCBtZXRob2QgPSAiY29tcGxldGUiKQ0KYGBgDQoNCmBgYHtyIHBlYXJzb25fdHJlZV9yaG9lbiwgZmlnLmhlaWdodD03fQ0KcGFyKGJnID0gIndoaXRlIiwgbWZyb3c9YygxLCAxKSkNCnBsb3RDb2xvcmVkQ2x1c3RlcnModHJlZV9wZWFyc29uX3Job2VuLCBsYWJzID0gcm93Lm5hbWVzKG1ldGFkYXRhX3RhYmxlKSwNCiAgICAgICAgICAgICAgICAgICAgeWxhYiA9IE5BLCB4bGFiID0gTkEsIGNleCA9IDEsIGxhcyA9IDEsDQogICAgICAgICAgICAgICAgICAgIGNvbHMgPSBtZXRhZGF0YV90YWJsZSRjb2xvciwgY29sID0gImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgICAgbWFpbiA9ICJTYW1wbGVzIFBlYXJzb24gZGlzdGFuY2UgaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcsDQpjb21wbGV0ZSBsaW5rYWdlLCBSLiBlbmNsZW5zaXMgZ2VuZXMuIikNCmBgYA0KDQpBZ2Fpbiwgc2FtcGxlcyBhcmUgbmF0dXJhbGx5IHNlcGFyYXRlZCBhY2NvcmRpbmcgdG8gdGhlaXIgaW5jdWJhdGlvbiBjb25kaXRpb24gZm9yICpSLiBlbmNsZW5zaXMqLg0KDQoNCmBgYHtyIGdlbmVfdHJlZV9kaW9odSwgaW5jbHVkZT1GQUxTRSwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0NCg0KIyBHZW5lIHRyZWUgd2l0aCBQZWFyc29uIGNvcnJlbGF0aW9uICMjIyMNCm1lc3NhZ2UoIkRyYXdpbmcgZ2VuZSB0cmVlIikNCg0KIyBQZWFyc29uIGRpc3RhbmNlIGdlbmUNCmRpc3RfZ2VuZV9wZWFyc29uX2Rpb2h1IDwtIGFzLmRpc3QoMSAtIGNvcih0KGRpb2h1X2NsciksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZSA9ICJldmVyeXRoaW5nIiwgbWV0aG9kID0gInBlYXJzb24iKSkNCg0KIyB0cmVlDQp0cmVlX2dlbmVfcGVhcnNvbl9kaW9odSA8LSBoY2x1c3QoZGlzdF9nZW5lX3BlYXJzb25fZGlvaHUsIG1ldGhvZCA9ICJjb21wbGV0ZSIpDQpgYGANCg0KDQpgYGB7ciBjdXRfdHJlZV9kaW9odSwgaW5jbHVkZT1GQUxTRSwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0NCiMgTGV0J3MgdHJ5IGN1dHRpbmcgdGhlIHRyZWUgaW50byA4IGNsdXN0ZXJzIGF0IHRoZSBoZWlnaHQgMS45Nw0KDQpjbHVzdGVyc19nZW5lX3BlYXJzb25fZGlvaHUgPC0gY3V0cmVlKHRyZWVfZ2VuZV9wZWFyc29uX2Rpb2h1LCBoPTEuOTcpDQoNCiMgSG93IG1hbnkgZ2VuZXMgYXJlIGluIGVhY2ggY2x1c3Rlcj8NCiN0YWJsZShjbHVzdGVyc19nZW5lX3BlYXJzb25fZGlvaHUpDQpgYGANCg0KYGBge3Igc2F2ZV9nZW5lX2NsdXN0ZXJzX2Rpb2h1LCBpbmNsdWRlPUZBTFNFLCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQ0KIyBTYXZpbmcgY2x1c3RlcmluZyByZXN1bHRzIGluIGdlbmUgZGF0YWZyYW1lIA0KZ2VuZV9zdGF0X25vcm1fZGlvaHUgPC0gZ2VuZV9zdGF0X25vcm1bZGlvaHVfZ2VuZWlkLF0NCmdlbmVfc3RhdF9ub3JtX2Rpb2h1JGNsdXN0ZXIgPC0gY2x1c3RlcnNfZ2VuZV9wZWFyc29uX2Rpb2h1DQoNCg0KIyBXZSBhZGQgdGhlIGNsdXN0ZXIgaW5mb3JtYXRpb24gaW4gdGhlIG1vc3RfZXhwcmVzc2VkX2dlbmVzX3N0YXQNCm15X2NvbG9ycyA9IGMoIm9yYW5nZSIsICJibHVlIiwgImRhcmtyZWQiLCAic2t5Ymx1ZSIsICJkYXJrZ3JlZW4iLCAicGluayIsICJncmVlbiIsICJyZWQiKQ0KDQojcGxvdCh0cmVlX2dlbmVfcGVhcnNvbl9kaW9odSwgbGFzID0gMSwgDQojICAgICB5bGFiID0gTkEsIHhsYWIgPSBOQSwgY2V4ID0gMC4xLCBoYW5nID0gLTEsIGNvbCA9ICJncmV5IiwNCiMgICAgIG1haW4gPSAiRC4gaHVuZ2FyaWNhIGdlbmVzIFBlYXJzb24gZGlzdGFuY2UgaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcsIGNvbXBsZXRlIGxpbmthZ2UiKQ0KDQojICByZWN0LmhjbHVzdCh0cmVlX2dlbmVfcGVhcnNvbl9kaW9odSwgaD0xLjk3LCBib3JkZXIgPSBteV9jb2xvcnMpDQpgYGANCg0KDQpgYGB7ciBnZW5lX2NsdXN0ZXJpbmdfcHNlZ3IsIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9DQojIyMjIEdlbmUgdHJlZSB3aXRoIFBlYXJzb24gY29ycmVsYXRpb24gIyMjIw0KbWVzc2FnZSgiRHJhd2luZyBnZW5lIHRyZWUiKQ0KDQojIFBlYXJzb24gZGlzdGFuY2UgZ2VuZQ0KZGlzdF9nZW5lX3BlYXJzb25fcHNlZ3IgPC0gYXMuZGlzdCgxIC0gY29yKHQocHNlZ3JfY2xyKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZSA9ICJldmVyeXRoaW5nIiwgbWV0aG9kID0gInBlYXJzb24iKSkNCg0KIyB0cmVlDQp0cmVlX2dlbmVfcGVhcnNvbl9wc2VnciA8LSBoY2x1c3QoZGlzdF9nZW5lX3BlYXJzb25fcHNlZ3IsIG1ldGhvZCA9ICJjb21wbGV0ZSIpDQpgYGANCg0KYGBge3IgY3V0X3RyZWVfcHNlZ3IsIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9DQpjbHVzdGVyc19nZW5lX3BlYXJzb25fcHNlZ3IgPC0gY3V0cmVlKHRyZWVfZ2VuZV9wZWFyc29uX3BzZWdyLCBoPTEuOTIpDQoNCiMgSG93IG1hbnkgZ2VuZXMgYXJlIGluIGVhY2ggY2x1c3Rlcj8NCiN0YWJsZShjbHVzdGVyc19nZW5lX3BlYXJzb25fcHNlZ3IpDQpgYGANCg0KYGBge3Igc2F2ZV9nZW5lX2NsdXN0ZXJzX3BzZWdyLCBpbmNsdWRlPUZBTFNFLCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQ0KIyBTYXZpbmcgY2x1c3RlcmluZyByZXN1bHRzIGluIGdlbmUgZGF0YWZyYW1lIA0KIyBnZW5lX3N0YXRfbm9ybV9wc2VnciA8LSBzbGljZV90YWlsKGdlbmVfc3RhdF9ub3JtW3BzZWdyX2dlbmVpZCxdLCBuPS0yKQ0KZ2VuZV9zdGF0X25vcm1fcHNlZ3IgPC0gZ2VuZV9zdGF0X25vcm1bcHNlZ3JfZ2VuZWlkLF0NCmdlbmVfc3RhdF9ub3JtX3BzZWdyJGNsdXN0ZXIgPC0gY2x1c3RlcnNfZ2VuZV9wZWFyc29uX3BzZWdyDQoNCg0KIyBXZSBhZGQgdGhlIGNsdXN0ZXIgaW5mb3JtYXRpb24gaW4gdGhlIG1vc3RfZXhwcmVzc2VkX2dlbmVzX3N0YXQNCm15X2NvbG9ycyA9IGMoIm9yYW5nZSIsICJibHVlIiwgImRhcmtyZWQiLCAic2t5Ymx1ZSIsICJkYXJrZ3JlZW4iLCAicGluayIsICJncmVlbiIsICJyZWQiKQ0KDQojcGxvdCh0cmVlX2dlbmVfcGVhcnNvbl9wc2VnciwgbGFzID0gMSwgDQojICAgICB5bGFiID0gTkEsIHhsYWIgPSBOQSwgY2V4ID0gMC4xLCBoYW5nID0gLTEsIGNvbCA9ICJncmV5IiwNCiMgICAgIG1haW4gPSAiUC4gZ3JhbWluaXMgZ2VuZXMgUGVhcnNvbiBkaXN0YW5jZSBoaWVyYXJjaGljYWwgY2x1c3RlcmluZywgY29tcGxldGUgbGlua2FnZSIpDQoNCiMgIHJlY3QuaGNsdXN0KHRyZWVfZ2VuZV9wZWFyc29uX3BzZWdyLCBoPTEuOTIsIGJvcmRlciA9IG15X2NvbG9ycykNCmBgYA0KDQoNCmBgYHtyIGdlbmVfY2x1c3RlcmluZ19wc2VzeSwgaW5jbHVkZT1GQUxTRSwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0NCiMjIyMgR2VuZSB0cmVlIHdpdGggUGVhcnNvbiBjb3JyZWxhdGlvbiAjIyMjDQptZXNzYWdlKCJEcmF3aW5nIGdlbmUgdHJlZSIpDQoNCiMgUGVhcnNvbiBkaXN0YW5jZSBnZW5lDQpkaXN0X2dlbmVfcGVhcnNvbl9wc2VzeSA8LSBhcy5kaXN0KDEgLSBjb3IodChwc2VzeV9jbHIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlID0gImV2ZXJ5dGhpbmciLCBtZXRob2QgPSAicGVhcnNvbiIpKQ0KDQojIHRyZWUNCnRyZWVfZ2VuZV9wZWFyc29uX3BzZXN5IDwtIGhjbHVzdChkaXN0X2dlbmVfcGVhcnNvbl9wc2VzeSwgbWV0aG9kID0gImNvbXBsZXRlIikNCmBgYA0KDQpgYGB7ciBjdXRfdHJlZV9wc2VzeSwgaW5jbHVkZT1GQUxTRSwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0NCmNsdXN0ZXJzX2dlbmVfcGVhcnNvbl9wc2VzeSA8LSBjdXRyZWUodHJlZV9nZW5lX3BlYXJzb25fcHNlc3ksIGg9MS45MSkNCg0KIyBIb3cgbWFueSBnZW5lcyBhcmUgaW4gZWFjaCBjbHVzdGVyPw0KI3RhYmxlKGNsdXN0ZXJzX2dlbmVfcGVhcnNvbl9wc2VzeSkNCmBgYA0KDQpgYGB7ciBzYXZlX2dlbmVfY2x1c3RlcnNfcHNlc3ksIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9DQojIFNhdmluZyBjbHVzdGVyaW5nIHJlc3VsdHMgaW4gZ2VuZSBkYXRhZnJhbWUgDQojIGdlbmVfc3RhdF9ub3JtX3BzZXN5IDwtIHNsaWNlX3RhaWwoZ2VuZV9zdGF0X25vcm1bcHNlc3lfZ2VuZWlkLF0sIG49LTIpDQpnZW5lX3N0YXRfbm9ybV9wc2VzeSA8LSBnZW5lX3N0YXRfbm9ybVtwc2VzeV9nZW5laWQsXQ0KZ2VuZV9zdGF0X25vcm1fcHNlc3kkY2x1c3RlciA8LSBjbHVzdGVyc19nZW5lX3BlYXJzb25fcHNlc3kNCg0KDQojIFdlIGFkZCB0aGUgY2x1c3RlciBpbmZvcm1hdGlvbiBpbiB0aGUgbW9zdF9leHByZXNzZWRfZ2VuZXNfc3RhdA0KbXlfY29sb3JzID0gYygib3JhbmdlIiwgImJsdWUiLCAiZGFya3JlZCIsICJza3libHVlIiwgImRhcmtncmVlbiIsICJwaW5rIiwgImdyZWVuIiwgInJlZCIpDQoNCiNwbG90KHRyZWVfZ2VuZV9wZWFyc29uX3BzZXN5LCBsYXMgPSAxLCANCiMgICAgIHlsYWIgPSBOQSwgeGxhYiA9IE5BLCBjZXggPSAwLjEsIGhhbmcgPSAtMSwgY29sID0gImdyZXkiLA0KIyAgICAgbWFpbiA9ICJQLiBzeXJpbmdhZSBnZW5lcyBQZWFyc29uIGRpc3RhbmNlIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nLCBjb21wbGV0ZSBsaW5rYWdlIikNCg0KIyAgcmVjdC5oY2x1c3QodHJlZV9nZW5lX3BlYXJzb25fcHNlc3ksIGg9MS45MSwgYm9yZGVyID0gbXlfY29sb3JzKQ0KYGBgDQoNCg0KYGBge3IgZ2VuZV9jbHVzdGVyaW5nX3Job2VuLCBpbmNsdWRlPUZBTFNFLCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQ0KIyMjIyBHZW5lIHRyZWUgd2l0aCBQZWFyc29uIGNvcnJlbGF0aW9uICMjIyMNCm1lc3NhZ2UoIkRyYXdpbmcgZ2VuZSB0cmVlIikNCg0KIyBQZWFyc29uIGRpc3RhbmNlIGdlbmUNCmRpc3RfZ2VuZV9wZWFyc29uX3Job2VuIDwtIGFzLmRpc3QoMSAtIGNvcih0KHJob2VuX2NsciksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2UgPSAiZXZlcnl0aGluZyIsIG1ldGhvZCA9ICJwZWFyc29uIikpDQoNCiMgdHJlZQ0KdHJlZV9nZW5lX3BlYXJzb25fcmhvZW4gPC0gaGNsdXN0KGRpc3RfZ2VuZV9wZWFyc29uX3Job2VuLCBtZXRob2QgPSAiY29tcGxldGUiKQ0KYGBgDQoNCmBgYHtyIGN1dF90cmVlX3Job2VuLCBpbmNsdWRlPUZBTFNFLCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQ0KY2x1c3RlcnNfZ2VuZV9wZWFyc29uX3Job2VuIDwtIGN1dHJlZSh0cmVlX2dlbmVfcGVhcnNvbl9yaG9lbiwgaD0xLjgpDQoNCiMgSG93IG1hbnkgZ2VuZXMgYXJlIGluIGVhY2ggY2x1c3Rlcj8NCiN0YWJsZShjbHVzdGVyc19nZW5lX3BlYXJzb25fcmhvZW4pDQpgYGANCg0KYGBge3Igc2F2ZV9nZW5lX2NsdXN0ZXJzX3Job2VuLCBpbmNsdWRlPUZBTFNFLCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQ0KIyBTYXZpbmcgY2x1c3RlcmluZyByZXN1bHRzIGluIGdlbmUgZGF0YWZyYW1lIA0KIyBnZW5lX3N0YXRfbm9ybV9yaG9lbiA8LSBzbGljZV90YWlsKGdlbmVfc3RhdF9ub3JtW3Job2VuX2dlbmVpZCxdLCBuPS0yKQ0KZ2VuZV9zdGF0X25vcm1fcmhvZW4gPC0gZ2VuZV9zdGF0X25vcm1bcmhvZW5fZ2VuZWlkLF0NCmdlbmVfc3RhdF9ub3JtX3Job2VuJGNsdXN0ZXIgPC0gY2x1c3RlcnNfZ2VuZV9wZWFyc29uX3Job2VuDQoNCg0KIyBXZSBhZGQgdGhlIGNsdXN0ZXIgaW5mb3JtYXRpb24gaW4gdGhlIG1vc3RfZXhwcmVzc2VkX2dlbmVzX3N0YXQNCm15X2NvbG9ycyA9IGMoIm9yYW5nZSIsICJibHVlIiwgImRhcmtyZWQiLCAic2t5Ymx1ZSIsICJkYXJrZ3JlZW4iLCAicGluayIsICJncmVlbiIsICJyZWQiKQ0KDQojcGxvdCh0cmVlX2dlbmVfcGVhcnNvbl9yaG9lbiwgbGFzID0gMSwgDQojICAgICB5bGFiID0gTkEsIHhsYWIgPSBOQSwgY2V4ID0gMC4xLCBoYW5nID0gLTEsIGNvbCA9ICJncmV5IiwNCiMgICAgIG1haW4gPSAiUi4gZW5jbGVuc2lzIGdlbmVzIFBlYXJzb24gZGlzdGFuY2UgaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcsIGNvbXBsZXRlIGxpbmthZ2UiKQ0KDQojICByZWN0LmhjbHVzdCh0cmVlX2dlbmVfcGVhcnNvbl9yaG9lbiwgaD0xLjgsIGJvcmRlciA9IG15X2NvbG9ycykNCmBgYA0KDQoNCg0KYGBge3IgaGVhdG1hcF9kaW9odSwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9NywgaW5jbHVkZT1GQUxTRSwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0NCg0KIyMjIEJpY2x1c3RlcmluZyB7LnRhYnNldH0NCiMjIyMgKkRpb3N6ZWdpYSBodW5nYXJpY2EqDQoNCiMjIyMgSGVhdG1hcCB3aXRoIGJpY2x1c3RlcmluZyAjIyMjDQptZXNzYWdlKCJoZWF0bWFwIHdpdGggYmljbHVzdGVyaW5nIikNCg0KYW5ub3RfY2x1c3RfZGlvaHUgPSBkYXRhLmZyYW1lKGFzLmZhY3RvcihnZW5lX3N0YXRfbm9ybV9kaW9odSRjbHVzdGVyKSkNCmNvbG5hbWVzKGFubm90X2NsdXN0X2Rpb2h1KSA8LSAiY2x1c3RlciINCnJvd25hbWVzKGFubm90X2NsdXN0X2Rpb2h1KSA8LSByb3duYW1lcyhkaW9odV9jbHIpDQoNCnBoZWF0bWFwKGRpb2h1X2NsciwNCiAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsDQogICAgICAgICBjbHVzdGVyX2NvbHMgPSBUUlVFLA0KICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gZGlzdF9nZW5lX3BlYXJzb25fZGlvaHUsDQogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHMgPSBkaXN0X3BlYXJzb25fZGlvaHUsDQogICAgICAgICBib3JkZXJfY29sb3IgPSBOQSwNCiAgICAgICAgIHNob3dfcm93bmFtZXMgPSBGQUxTRSwNCiAgICAgICAgIGFubm90YXRpb25fcm93ID0gYW5ub3RfY2x1c3RfZGlvaHUsDQogICAgICAgICBhbm5vdGF0aW9uX25hbWVzX3JvdyA9IEZBTFNFLA0KICAgICAgICAgY3V0cmVlX3Jvd3MgPSA4LA0KICAgICAgICAgY3V0cmVlX2NvbHMgPSAyLA0KICAgICAgICAgc2NhbGUgPSAicm93IiwNCiAgICAgICAgIHVzZV9yYXN0ZXIgPSBUUlVFLA0KICAgICAgICAgYW5nbGVfY29sID0gIjAiLA0KICAgICAgICAgbWFpbiA9ICJCaWNsdXN0ZXJpbmcgb2YgRC4gaHVuZ2FyaWNhIGdlbmVzIChQZWFyc29uIGRpc3RhbmNlKSANCmFuZCBzYW1wbGVzIChQZWFyc29uIGRpc3RhbmNlKSIpDQpgYGANCg0KDQoNCmBgYHtyIGhlYXRtYXBfcHNlZ3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTcsIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9DQojIyMjICpQc2V1ZG9tb25hcyBncmFtaW5pcyoNCg0KIyMjIyBIZWF0bWFwIHdpdGggYmljbHVzdGVyaW5nICMjIyMNCm1lc3NhZ2UoImhlYXRtYXAgd2l0aCBiaWNsdXN0ZXJpbmciKQ0KDQphbm5vdF9jbHVzdF9wc2VnciA9IGRhdGEuZnJhbWUoYXMuZmFjdG9yKGdlbmVfc3RhdF9ub3JtX3BzZWdyJGNsdXN0ZXIpKQ0KY29sbmFtZXMoYW5ub3RfY2x1c3RfcHNlZ3IpIDwtICJjbHVzdGVyIg0Kcm93bmFtZXMoYW5ub3RfY2x1c3RfcHNlZ3IpIDwtIHJvd25hbWVzKHBzZWdyX2NscikNCg0KcGhlYXRtYXAocHNlZ3JfY2xyLA0KICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwNCiAgICAgICAgIGNsdXN0ZXJfY29scyA9IFRSVUUsDQogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX3Jvd3MgPSBkaXN0X2dlbmVfcGVhcnNvbl9wc2VnciwNCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2VfY29scyA9IGRpc3RfcGVhcnNvbl9wc2VnciwNCiAgICAgICAgIGJvcmRlcl9jb2xvciA9IE5BLA0KICAgICAgICAgc2hvd19yb3duYW1lcyA9IEZBTFNFLA0KICAgICAgICAgYW5ub3RhdGlvbl9yb3cgPSBhbm5vdF9jbHVzdF9wc2VnciwNCiAgICAgICAgIGFubm90YXRpb25fbmFtZXNfcm93ID0gRkFMU0UsDQogICAgICAgICBjdXRyZWVfcm93cyA9IDMsDQogICAgICAgICBjdXRyZWVfY29scyA9IDIsDQogICAgICAgICBzY2FsZSA9ICJyb3ciLA0KICAgICAgICAgdXNlX3Jhc3RlciA9IFRSVUUsDQogICAgICAgICBhbmdsZV9jb2wgPSAiMCIsDQogICAgICAgICBtYWluID0gIkJpY2x1c3RlcmluZyBvZiBQLiBncmFtaW5pcyBnZW5lcyAoUGVhcnNvbiBkaXN0YW5jZSkgDQphbmQgc2FtcGxlcyAoUGVhcnNvbiBkaXN0YW5jZSkiKQ0KDQojIE9uIHZvaXQgY29tYmllbiBsZXMgw6ljaGFudGlsbG9ucyAibnVpdCIgc29udCBkaWZmw6lyZW50cyBsZXMgdW5zIGRlcyBhdXRyZXMuIExlcyDDqWNoYW50aWxsb25zICJqb3VyIiBzb250IHRyw6hzIHByb2NoZXMgZW50cmUgZXV4IGNhciBpbHMgcHLDqXNlbnRlbnQgcGFydG91dCBxdWFzaW1lbnQgcGFzIGQnZXhwcmVzc2lvbi4NCmBgYA0KDQoNCg0KYGBge3IgaGVhdG1hcF9wc2VzeSwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9NywgaW5jbHVkZT1GQUxTRSwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0NCiMjIyMgKlBzZXVkb21vbmFzIHN5cmluZ2FlKg0KDQojIyMjIEhlYXRtYXAgd2l0aCBiaWNsdXN0ZXJpbmcgIyMjIw0KbWVzc2FnZSgiaGVhdG1hcCB3aXRoIGJpY2x1c3RlcmluZyIpDQoNCmFubm90X2NsdXN0X3BzZXN5ID0gZGF0YS5mcmFtZShhcy5mYWN0b3IoZ2VuZV9zdGF0X25vcm1fcHNlc3kkY2x1c3RlcikpDQpjb2xuYW1lcyhhbm5vdF9jbHVzdF9wc2VzeSkgPC0gImNsdXN0ZXIiDQpyb3duYW1lcyhhbm5vdF9jbHVzdF9wc2VzeSkgPC0gcm93bmFtZXMocHNlc3lfY2xyKQ0KDQpwaGVhdG1hcChwc2VzeV9jbHIsDQogICAgICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLA0KICAgICAgICAgY2x1c3Rlcl9jb2xzID0gVFJVRSwNCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IGRpc3RfZ2VuZV9wZWFyc29uX3BzZXN5LA0KICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9jb2xzID0gZGlzdF9wZWFyc29uX3BzZXN5LA0KICAgICAgICAgYm9yZGVyX2NvbG9yID0gTkEsDQogICAgICAgICBzaG93X3Jvd25hbWVzID0gRkFMU0UsDQogICAgICAgICBhbm5vdGF0aW9uX3JvdyA9IGFubm90X2NsdXN0X3BzZXN5LA0KICAgICAgICAgYW5ub3RhdGlvbl9uYW1lc19yb3cgPSBGQUxTRSwNCiAgICAgICAgIGN1dHJlZV9yb3dzID0gNiwNCiAgICAgICAgIGN1dHJlZV9jb2xzID0gMiwNCiAgICAgICAgIHNjYWxlID0gInJvdyIsDQogICAgICAgICB1c2VfcmFzdGVyID0gVFJVRSwNCiAgICAgICAgIGFuZ2xlX2NvbCA9ICIwIiwNCiAgICAgICAgIG1haW4gPSAiQmljbHVzdGVyaW5nIG9mIFAuIHN5cmluZ2FlIGdlbmVzIChQZWFyc29uIGRpc3RhbmNlKSANCmFuZCBzYW1wbGVzIChQZWFyc29uIGRpc3RhbmNlKSIpDQpgYGANCg0KDQoNCmBgYHtyIGhlYXRtYXBfcmhvZW4sIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTcsIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9DQojIyMjICpSaG9kb2NvY2N1cyBlbmNsZW5zaXMqDQoNCiMjIyMgSGVhdG1hcCB3aXRoIGJpY2x1c3RlcmluZyAjIyMjDQptZXNzYWdlKCJoZWF0bWFwIHdpdGggYmljbHVzdGVyaW5nIikNCg0KYW5ub3RfY2x1c3RfcmhvZW4gPSBkYXRhLmZyYW1lKGFzLmZhY3RvcihnZW5lX3N0YXRfbm9ybV9yaG9lbiRjbHVzdGVyKSkNCmNvbG5hbWVzKGFubm90X2NsdXN0X3Job2VuKSA8LSAiY2x1c3RlciINCnJvd25hbWVzKGFubm90X2NsdXN0X3Job2VuKSA8LSByb3duYW1lcyhyaG9lbl9jbHIpDQoNCnBoZWF0bWFwKHJob2VuX2NsciwNCiAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsDQogICAgICAgICBjbHVzdGVyX2NvbHMgPSBUUlVFLA0KICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gZGlzdF9nZW5lX3BlYXJzb25fcmhvZW4sDQogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHMgPSBkaXN0X3BlYXJzb25fcmhvZW4sDQogICAgICAgICBib3JkZXJfY29sb3IgPSBOQSwNCiAgICAgICAgIHNob3dfcm93bmFtZXMgPSBGQUxTRSwNCiAgICAgICAgIGFubm90YXRpb25fcm93ID0gYW5ub3RfY2x1c3RfcmhvZW4sDQogICAgICAgICBhbm5vdGF0aW9uX25hbWVzX3JvdyA9IEZBTFNFLA0KICAgICAgICAgY3V0cmVlX3Jvd3MgPSA2LA0KICAgICAgICAgY3V0cmVlX2NvbHMgPSAyLA0KICAgICAgICAgc2NhbGUgPSAicm93IiwNCiAgICAgICAgIHVzZV9yYXN0ZXIgPSBUUlVFLA0KICAgICAgICAgYW5nbGVfY29sID0gIjAiLA0KICAgICAgICAgbWFpbiA9ICJCaWNsdXN0ZXJpbmcgb2YgUi4gZW5jbGVuc2lzIGdlbmVzIChQZWFyc29uIGRpc3RhbmNlKSANCmFuZCBzYW1wbGVzIChQZWFyc29uIGRpc3RhbmNlKSIpDQpgYGANCg0KIyMgRGlmZmVyZW50aWFsIGFuYWx5c2VzIHdpdGggTVRYbW9kZWwgKHdob2xlIGNvbW11bml0eSBtZXRhdHJhbnNjcmlwdG9taWNzIGRhdGEpDQoNCk1UWG1vZGVsIHdhcyB1c2VkIG9uIHRoZSBjb21wbGV0ZSBjb21tdW5pdHkgYXQgb25jZS4gDQpBcyBpbnB1dCwgZmlsdGVyZWQgZGF0YSAod2l0aG91dCB0aGUgdW5kZXRlY3RlZCBnZW5lcykgYnV0IHVudHJhbnNmb3JtZWQgd2FzIGdpdmVuIHRvIE1UWG1vZGVsLCBhcyBpdCBwZXJmb3JtcyBpdHMgb3duIENMUiBub3JtYWxpc2F0aW9uLiANCg0KYGFuYWx5c2lzX21ldGhvZCA9ICdMTSdgIA0KDQpgY29ycmVjdGlvbiA9ICdCSCdgLCANCg0KDQoNCmBgYHtyIGZpdF9kYXRhX3JhdywgZXZhbD1GQUxTRX0NCmZpdF9kYXRhIDwtIE1UWG1vZGVsKA0KICAgIGNvdW50c19zdGFuZGFyZCwgbWV0YWRhdGFfdGFibGUsICdNVFhtb2RlbF9vdXRwdXQnLA0KICAgIGNvcmVzID0gMiwNCiAgICBmaXhlZF9lZmZlY3RzID0gYygndGVtcGVyYXR1cmUnKSwNCiAgICByZWZlcmVuY2UgPSBjKCJ0ZW1wZXJhdHVyZSw1IiksDQogICAgbWluX2FidW5kYW5jZSA9IDAsDQogICAgbWluX3ByZXZhbGVuY2UgPSAwLA0KICAgIG5vcm1hbGl6YXRpb24gPSAnQ0xSJywNCiAgICBhbmFseXNpc19tZXRob2QgPSAnTE0nLA0KICAgIGNvcnJlY3Rpb24gPSAnQkgnLA0KICAgIHN0YW5kYXJkaXplID0gRkFMU0UsDQogICAgdHJhbnNmb3JtID0gJ05PTkUnLA0KICAgIHBsb3Rfc2NhdHRlciA9IEZBTFNFLA0KICAgIHBsb3RfaGVhdG1hcCA9IFRSVUUpDQoNCmBgYA0KDQpgYGB7ciBNVFhfbW9kZWxfdm9sY2Fub19wbG90LCBldmFsPUZBTFNFfQ0KIyBwYXIobWFyPWMoNSw1LDUsNSksIGNleD0xLjAsIGNleC5tYWluPTEuNCwgY2V4LmF4aXM9MS40LCBjZXgubGFiPTEuNCkNCiMgdG9wVCA8LSByZWFkLmNzdigiTVRYbW9kZWxfb3V0cHV0L2FsbF9yZXN1bHRzLnRzdiIsIHNlcD0iXHQiLCByb3cubmFtZXM9ImZlYXR1cmUiKQ0KIyANCiMgI3RvcFQgPC0gYXMuZGF0YS5mcmFtZShyZXNERVNlcSkNCiMgDQojICNBZGp1c3RlZCBQIHZhbHVlcyAoRkRSIFEgdmFsdWVzKQ0KIyB3aXRoKHRvcFQsIHBsb3QoY29lZiwgLWxvZzEwKHF2YWwpLCBwY2g9MjAsIG1haW49IlZvbGNhbm8gcGxvdCBjb21tdW5pdHkiLCBjb2w9IndoaXRlIiwgeGxhYj1icXVvdGUofk1UWG1vZGVsfmNvZWZmaWNpZW50KSwgeWxhYj1icXVvdGUofi1sb2dbMTBdfnF+dmFsdWUpLCB4bGltPWMoMC40LC0wLjQpLCB5bGltPWMoMC42LDEuMikpKQ0KIyANCiMgd2l0aChzdWJzZXQodG9wVCwgcXZhbDw9MC4yICYgY29lZjw9LTAuMSksIHBvaW50cyhjb2VmLCAtbG9nMTAocXZhbCksIHBjaD0yMSwgY29sPSJibHVlIiwgYmc9ImxpZ2h0Ymx1ZSIsIGNleD0xLjQsIGx3ZD0yKSkNCiMgd2l0aChzdWJzZXQodG9wVCwgcXZhbDw9MC4yICYgY29lZj49MC4xKSwgcG9pbnRzKGNvZWYsIC1sb2cxMChxdmFsKSwgcGNoPTIxLCBjb2w9Im9yYW5nZSIsIGJnPSJnb2xkIiwgY2V4PTEuNCwgbHdkPTIpKQ0KIyB3aXRoKHN1YnNldCh0b3BULCBxdmFsPjAuMiB8IGFicyhjb2VmKTwwLjEpLCBwb2ludHMoY29lZiwgLWxvZzEwKHF2YWwpLCBwY2g9MjEsIGNvbD0iYmxhY2siLCBiZz0iZ3JleSIsIGNleD0xLjQsIGx3ZD0yKSkNCiMgDQojIA0KIyANCiMgI0FkZCBsaW5lcyBmb3IgYWJzb2x1dGUgRkM+MSBhbmQgUC12YWx1ZSBjdXQtb2ZmIGF0IEZEUiBwIGFkanVzdGVkIHZhbHVlPDAuMg0KIyBhYmxpbmUodj0wLCBjb2w9ImJsYWNrIiwgbHR5PTMsIGx3ZD0xLjApDQojIGFibGluZSh2PS0wLjEsIGNvbD0iYmxhY2siLCBsdHk9NCwgbHdkPTEuMCkNCiMgYWJsaW5lKHY9MC4xLCBjb2w9ImJsYWNrIiwgbHR5PTQsIGx3ZD0xLjApDQojIGFibGluZShoPS1sb2cxMCgwLjIpLCBjb2w9ImJsYWNrIiwgbHR5PTQsIGx3ZD0xLjApDQojICNhYmxpbmUoaD0tbG9nMTAobWF4KHRvcFQkcHZhbHVlW3RvcFQkcGFkajwwLjJdLCBuYS5ybT1UUlVFKSksIGNvbD0iYmxhY2siLCBsdHk9NCwgbHdkPTIuMCkNCg0KYGBgDQoNCmBgYHtyIGZpbHRlcl9NVFhtb2RlbF9yZXN1bHRzfQ0KDQojIExvYWRpbmcgTVRYbW9kZWwgcmVzdWx0cw0KcmVzX210eCA8LSByZWFkLmNzdigiLi4vc2NyaXB0cy9NVFhtb2RlbF9vdXRwdXQvYWxsX3Jlc3VsdHMudHN2Iiwgc2VwPSJcdCIsIHJvdy5uYW1lcz0iZmVhdHVyZSIpDQoNCg0KdHJ5Q2F0Y2goew0KICBpbm5lcl9qb2luKHJvd25hbWVzX3RvX2NvbHVtbihyZXNfbXR4KSwgYW5ub3RhdGlvbl90YWJsZV9maWcsIGJ5PWMoInJvd25hbWUiID0gImdlbmUiKSkgLT4gcmVzX210eF9maWcNCiAgcmVzX210eF9maWcgJT4lIGZpbHRlcihhYnMocXZhbCkgPD0gMC4yKSAtPiByZXNfbXR4X2ZpZw0KICB9LA0KICBlcnJvcj1mdW5jdGlvbihlKXtzdHIoZSkNCiAgfQ0KKQ0KDQoNCiMjIERhdGEgZm9yIGZpbmFsIHRhYmxlDQphbm5vdGF0aW9uX3RhYmxlX2xvbmcgPC0gcmVhZC5jc3YoIi4uL2RhdGEvYW5ub3RhdGlvbnNfZmluYWxfY29tbXVuaXR5X2xvbmcudHN2Iiwgc2VwPSJcdCIsIHJvdy5uYW1lcyA9ICJHZW5laWQiKQ0KDQp0cnlDYXRjaCh7DQogIGFubm90YXRpb25fdGFibGVfbG9uZyRnZW5lIDwtIHJvdy5uYW1lcyhhbm5vdGF0aW9uX3RhYmxlX2xvbmcpDQogIGlubmVyX2pvaW4ocm93bmFtZXNfdG9fY29sdW1uKHJlc19tdHgpLCBhbm5vdGF0aW9uX3RhYmxlX2xvbmcsIGJ5PWMoInJvd25hbWUiID0gImdlbmUiKSkgLT4gcmVzX210eF9maWx0DQogIHJlc19tdHhfZmlsdCAlPiUgZmlsdGVyKGFicyhxdmFsKSA8PSAwLjIpIC0+IHJlc19tdHhfZmlsdA0KICB9LA0KICBlcnJvcj1mdW5jdGlvbihlKXtzdHIoZSkNCiAgfQ0KKQ0KDQpgYGANCg0KDQojIyBEaWZmZXJlbnRpYWwgYW5hbHlzZXMgd2l0aCBERVNlcTIgKG1ldGF0cmFuc2NyaXB0b21pY3MgZGF0YSBzcGVjaWVzIGJ5IHNwZWNpZXMpDQoNCkFzIGEgY29tcGxlbWVudGFyeSBhcHByb2FjaCwgc2VwYXJhdGUgZGlmZmVyZW50aWFsIGFuYWx5c2VzIHdlcmUgY29uZHVjdGVkIGZvciBlYWNoIHNwZWNpZXMgc2VwYXJhdGVseSB3aXRoIERFU2VxMi4NCg0KIyMjIERFU2VxMiBhbmFseXNlcyBwcmVwYXJhdGlvbg0KDQpgYGB7ciBjb252ZXJ0aW5nX3RvX2ZhY3RvcnN9DQptZXRhZGF0YV90YWJsZSR0ZW1wZXJhdHVyZSA8LSBmYWN0b3IobWV0YWRhdGFfdGFibGUkdGVtcGVyYXR1cmUpDQoNCmBgYA0KDQpXZSB1c2UgZmlsdGVyZWQgY291bnRzIGRhdGEgKG9ubHkgZ2VuZXMgZGV0ZWN0ZWQgaW4gYXQgbGVhc3QgNzAlIG9mIGJpb2xvZ2ljYWwgc2FtcGxlcykuIFplcm9lcyBhcmUgY29uc2VydmVkIGFzIGlzLiBXZSByb3VuZCB0aGUgY291bnRzIG1hdHJpeCBiZWZvcmUgcGVyZm9ybWluZyBERVNlcTIgYW5hbHlzaXMuDQoNCmBgYHtyIERFU2VxMl9kZn0NCmRpb2h1X2RmIDwtIGNvdW50c19maWx0ZXJlZFtkaW9odV9nZW5laWQsXQ0KcHNlZ3JfZGYgPC0gY291bnRzX2ZpbHRlcmVkW3BzZWdyX2dlbmVpZCxdDQpwc2VzeV9kZiA8LSBjb3VudHNfZmlsdGVyZWRbcHNlc3lfZ2VuZWlkLF0NCnJob2VuX2RmIDwtIGNvdW50c19maWx0ZXJlZFtyaG9lbl9nZW5laWQsXQ0KDQpgYGANCg0KYGBge3IgaW5pdGlhbGl6ZV9yZXNfZ2VudXNfZGZ9DQpyZXNfZGYgPC0gZGF0YS5mcmFtZShnZW5lPWNoYXJhY3RlcigpLCANCiAgICAgICAgICAgICAgICAgICAgIGJhc2VNZWFuPW51bWVyaWMoKSwNCiAgICAgICAgICAgICAgICAgICAgIGxvZzJGb2xkQ2hhbmdlPW51bWVyaWMoKSwgDQogICAgICAgICAgICAgICAgICAgICBsZmNTRT1udW1lcmljKCksIA0KICAgICAgICAgICAgICAgICAgICAgc3RhdD1udW1lcmljKCksIA0KICAgICAgICAgICAgICAgICAgICAgcHZhbHVlPW51bWVyaWMoKSwgDQogICAgICAgICAgICAgICAgICAgICBwYWRqPW51bWVyaWMoKSwgDQogICAgICAgICAgICAgICAgICAgICBjb25kaXRpb249ZmFjdG9yKCksDQogICAgICAgICAgICAgICAgICAgICBTQU1QTEVfQ09NUEFSSVNPTj1mYWN0b3IoKSwNCiAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtPWZhY3RvcigpKQ0KYGBgDQoNCiMjIyAqRGlvc3plZ2lhIGh1bmdhcmljYSoNCg0KYGBge3IgREVTZXEyX2Rpb2h1XzIwMjR9DQpjb21wdXRlX2Rlc2VxMl9hbmFseXNpcyhkaW9odV9kZiwgDQogICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YV90YWJsZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICNzdWJzZXRfdmFyID0gInRlbXBlcmF0dXJlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAjc2VsZWN0ID0gIjMuNSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RfY29sPSJ0ZW1wZXJhdHVyZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgcmVmPSI1IiwgDQogICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ZWQ9IjE3IikgLT4gcmVzDQoNCnRyeUNhdGNoKHtyZXMkb3JnYW5pc20gPC0gIkQuIGh1bmdhcmljYSJ9LA0KICBlcnJvcj1mdW5jdGlvbihlKXtzdHIoZSkgIyBwcmludHMgc3RydWN0dXJlIG9mIGV4Y2VwdGlvbg0KICB9KQ0KDQpyZXNfZGYgPC0gcmJpbmQocmVzX2RmLCByZXMpIA0KDQpgYGANCg0KIyMjICpSaG9kb2NvY2N1cyBlbmNsZW5zaXMqDQoNCmBgYHtyIERFU2VxMl9yaG9lbl8yMDI0fQ0KDQpjb21wdXRlX2Rlc2VxMl9hbmFseXNpcyhyaG9lbl9kZiwgDQogICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YV90YWJsZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICNzdWJzZXRfdmFyID0gInRlbXBlcmF0dXJlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAjc2VsZWN0ID0gIjMuNSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RfY29sPSJ0ZW1wZXJhdHVyZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgcmVmPSI1IiwgDQogICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ZWQ9IjE3IikgLT4gcmVzDQoNCnRyeUNhdGNoKHtyZXMkb3JnYW5pc20gPC0gIlIuIGVuY2xlbnNpcyJ9LA0KICBlcnJvcj1mdW5jdGlvbihlKXtzdHIoZSkNCiAgfSkNCg0KcmVzX2RmIDwtIHJiaW5kKHJlc19kZiwgcmVzKSANCg0KYGBgDQoNCiMjIyAqUHNldWRvbW9uYXMgc3lyaW5nYWUqDQoNCmBgYHtyIERFU2VxMl9wc2VzeV8yMDI0fQ0KDQpjb21wdXRlX2Rlc2VxMl9hbmFseXNpcyhwc2VzeV9kZiwgDQogICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YV90YWJsZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICNzdWJzZXRfdmFyID0gInRlbXBlcmF0dXJlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAjc2VsZWN0ID0gIjMuNSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RfY29sPSJ0ZW1wZXJhdHVyZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgcmVmPSI1IiwgDQogICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ZWQ9IjE3IikgLT4gcmVzDQoNCnRyeUNhdGNoKHtyZXMkb3JnYW5pc20gPC0gIlAuIHN5cmluZ2FlIn0sDQogIGVycm9yPWZ1bmN0aW9uKGUpe3N0cihlKQ0KICB9KQ0KDQpyZXNfZGYgPC0gcmJpbmQocmVzX2RmLCByZXMpIA0KDQpgYGANCg0KIyMjICpQc2V1ZG9tb25hcyBncmFtaW5pcyoNCg0KYGBge3IgREVTZXEyX3BzZWdyXzIwMjR9DQoNCmNvbXB1dGVfZGVzZXEyX2FuYWx5c2lzKHBzZWdyX2RmLCANCiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhX3RhYmxlLA0KICAgICAgICAgICAgICAgICAgICAgICAgI3N1YnNldF92YXIgPSAidGVtcGVyYXR1cmUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICNzZWxlY3QgPSAiMy41IiwgDQogICAgICAgICAgICAgICAgICAgICAgICBjb250cmFzdF9jb2w9InRlbXBlcmF0dXJlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICByZWY9IjUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RlZD0iMTciKSAtPiByZXMNCg0KdHJ5Q2F0Y2goe3JlcyRvcmdhbmlzbSA8LSAiUC4gZ3JhbWluaXMifSwNCiAgZXJyb3I9ZnVuY3Rpb24oZSl7c3RyKGUpDQogIH0pDQoNCnJlc19kZiA8LSByYmluZChyZXNfZGYsIHJlcykgDQoNCmBgYA0KDQojIyMgRmlsdGVyIERFU2VxMiBkYXRhDQoNCmBgYHtyIHByZXBfZGZfREVTZXEyX3Bsb3R9DQoNCg0KdHJ5Q2F0Y2goew0KICByZXNfZGYgJT4lIGlubmVyX2pvaW4oYW5ub3RhdGlvbl90YWJsZV9maWcsIGJ5PSJnZW5lIikgLT4gdG1wX3Jlc19kZg0KICB0bXBfcmVzX2RmICU+JSBmaWx0ZXIocGFkaiA8PSAwLjIpIC0+IHJlc19kZXNlcV9maWcgICMmIGFicyhsb2cyRm9sZENoYW5nZSkgPj0gMQ0KICB9LA0KICBlcnJvcj1mdW5jdGlvbihlKXtzdHIoZSkNCiAgfQ0KKQ0KDQpybSh0bXBfcmVzX2RmKQ0KDQojIyBkYXRhIGZvciBmaW5hbCB0YWJsZQ0KIyBhbm5vdGF0aW9uX3RhYmxlX2xvbmcgPC0gcmVhZC5jc3YoIi4uLy4uL21vY2tfY29tbXVuaXRpZXMvZGF0YS9hbm5vdGF0aW9uc19maW5hbF9jb21tdW5pdHkudHN2Iiwgc2VwPSJcdCIsIHJvdy5uYW1lcyA9ICJHZW5laWQiKQ0KYW5ub3RhdGlvbl90YWJsZV9sb25nIDwtIHJlYWQuY3N2KCIuLi9kYXRhL2Fubm90YXRpb25zX2ZpbmFsX2NvbW11bml0eV9sb25nLnRzdiIsIHNlcD0iXHQiLCByb3cubmFtZXMgPSAiR2VuZWlkIikNCg0KdHJ5Q2F0Y2goew0KICBhbm5vdGF0aW9uX3RhYmxlX2xvbmckZ2VuZSA8LSByb3cubmFtZXMoYW5ub3RhdGlvbl90YWJsZV9sb25nKQ0KICByZXNfZGYgJT4lIGlubmVyX2pvaW4oYW5ub3RhdGlvbl90YWJsZV9sb25nLCBieT0iZ2VuZSIpIC0+IHJlc19kZg0KICByZXNfZGYgJT4lIGZpbHRlcihwYWRqIDw9IDAuMikgLT4gcmVzX2Rlc2VxX2ZpbHQgIyAmIGFicyhsb2cyRm9sZENoYW5nZSkgPj0gMQ0KICB9LA0KICBlcnJvcj1mdW5jdGlvbihlKXtzdHIoZSkNCiAgfQ0KKQ0KYGBgDQoNCiMjIyBTYXZlIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyAoREVHcykgYWxsIG1ldGhvZHMNCg0KYGBge3Igc2F2ZV9ERUdfY29tbXVfYWxsfQ0KDQp0ZW1wX2RmIDwtIHJpZ2h0X2pvaW4ocm93bmFtZXNfdG9fY29sdW1uKHJlc19tdHgpLCBhbm5vdGF0aW9uX3RhYmxlX2xvbmcsIGpvaW5fYnkoInJvd25hbWUiPT0iZ2VuZSIpKQ0KcmVuYW1lKHRlbXBfZGYsICJnZW5lIiA9ICJyb3duYW1lIikgLT4gdGVtcF9kZg0KDQoNCg0KYWxsX2dlbmVzIDwtIGZ1bGxfam9pbihyZXNfZGYsIHRlbXBfZGYsICBieT1jKCJnZW5lIiwgImxvY3VzX3RhZyIsICJ0cmFuc2NyaXB0SWQiLCAiT3JnYW5pc20iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaHIiLCAiU3RhcnQiLCAiRW5kIiwgIlN0cmFuZCIsICJMZW5ndGgiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwcm9kdWN0IiwgIkNPR19wcm9jZXNzIiwgIkNPR19jYXRlZ29yeSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNPR2lkIiwgIkdPcyIsICJDT0dfY2F0IiwgIkNPR19jYXRlZ29yeV9sb25nIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZWNOdW0iICksDQogICAgICAgICAgICAgICAgICAgICAgIHN1ZmZpeCA9IGMoIiIsICJ3IikpDQoNCnJtKHRlbXBfZGYpDQpjb2x1bW5zX3RvX3JlbW92ZSA8LSBncmVwKCIudyIsIG5hbWVzKGFsbF9nZW5lcykpDQphbGxfZ2VuZXMgJT4lIGRwbHlyOjpzZWxlY3QoLWNvbHVtbnNfdG9fcmVtb3ZlKSAlPiUgZmlsdGVyKHF2YWw8PTAuMiB8IHBhZGo8PTAuMiApIC0+IGFsbF9nZW5lc19maWx0ZXJlZA0KDQp3cml0ZS50YWJsZShhbGxfZ2VuZXNfZmlsdGVyZWQsICIuLi9yZXN1bHRzL0RFR19hbGxfbWV0aG9kc19jb21tdW5pdHkudHN2Iiwgc2VwPSdcdCcsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KDQp3cml0ZS50YWJsZShyZXNfZGYsICIuLi9yZXN1bHRzL0RFR19ERVNlcTJfYWxsX2NvbW11bml0eS50c3YiLCBzZXA9J1x0Jywgcm93Lm5hbWVzID0gRkFMU0UpDQpzaWduX2Rlc2VxMl9kZiA8LSByZXNfZGYNCmBgYA0KDQojIyBQbG90IERFR3MgYWxsIG1ldGhvZHMNCg0KDQpgYGB7ciBwbG90X2FsbF9kZWdzX3ZlcnRpY2FsLCBmaWcuaGVpZ2h0PTEyLCBmaWcuZHBpPTIwMCwgZmlnLndpZHRoPTEzfQ0KDQojIyMjIEJvdGggbWV0aG9kcyBERUdzDQoNCg0KZnVsbF9qb2luKGFsbF9nZW5lc19maWx0ZXJlZCwgYW5ub3RhdGlvbl90YWJsZV9maWcsIGJ5PSJnZW5lIikgLT4gZGF0YQ0KDQoNCmRhdGEkdGl0bGUgPC0gIkRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBTRCB2cyBXTiAoREVTZXEyICYgTVRYbW9kZWwpIg0KZGF0YSRPcmdhbmlzbSA8LSBmYWN0b3IoZGF0YSRvcmdhbmlzbSwgbGV2ZWxzPWMoIkQuIGh1bmdhcmljYSIsICJQLiBncmFtaW5pcyIsICJQLiBzeXJpbmdhZSIsICJSLiBlbmNsZW5zaXMiKSkNCg0KDQoNCg0KY3VzdG9tX3N0cmlwcyA8LSBzdHJpcF9uZXN0ZWQoYmFja2dyb3VuZF94ID0gZWxlbV9saXN0X3JlY3QoZmlsbCA9IGMoImxpZ2h0Z3JleSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY2llc19jb2xvdXJzW1siRC5odW5nYXJpY2EiXV0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY2llc19jb2xvdXJzW1siUC5zeXJpbmdhZSJdXSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzX2NvbG91cnNbWyJSLmVuY2xlbnNpcyJdXSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dF94ID0gbGlzdChlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGNvbG91ciA9ICJibGFjayIsIHNpemUgPSAxNyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRfdGV4dChmYWNlID0gIml0YWxpYyIsIGNvbG91ciA9ICJ3aGl0ZSIsIHNpemUgPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRfdGV4dChmYWNlID0gIml0YWxpYyIsIGNvbG91ciA9ICJ3aGl0ZSIsIHNpemUgPSAxNSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiLCBjb2xvdXIgPSAid2hpdGUiLCBzaXplID0gMTUpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5X2xheWVyX3ggPSBGQUxTRSkNCg0KDQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBjb2VmLCB5ID0gQ09HX2NhdGVnb3J5LnksICBjb2xvciA9IGFmdGVyX3NjYWxlKGFscGhhKGZpbGwsIDAuMykpLCBmaWxsPUNPR19jYXRlZ29yeV9sb25nLnksIGFscGhhPTAuNywgbGFiZWw9bmFtZV9maWd1cmUpKSArIA0KICBnZW9tX3BvaW50KGFlcyhhbHBoYT0wLjcpLCBwb3NpdGlvbj0iZG9kZ2UiKSArDQogIGdlb21fdmlvbGluKGFlcyhhbHBoYT0wLjMpLCBzaG93LmxlZ2VuZCA9IFRSVUUpICsNCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluPS1JbmYsIHhtYXg9MCwgeW1pbj0tSW5mLCB5bWF4PUluZiwgZmlsbD0iIzE4NGNhNSIsIGFscGhhPTAuMSkgKw0KICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MCwgeG1heD1JbmYsIHltaW49LUluZiwgeW1heD1JbmYsIGZpbGw9ImdvbGQiLCBhbHBoYT0wLjEpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIpICsNCiAgeWxhYigiQ09HIGNhdGVnb3J5IikgKw0KICB4bGFiKCJNVFhtb2RlbCBjb2VmZmljaWVudCIpICsNCiAgZ2dyZXBlbDo6Z2VvbV90ZXh0X3JlcGVsKG51ZGdlX3kgPSAwLjUsIHNlZ21lbnQuc2l6ZT0wLjEsIHNlZWQgPSA0MikgKw0KICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQobmNvbD0zKSwgYWxwaGE9Im5vbmUiLCBjb2xvcj0ibm9uZSIpICsgI2NvbG9yPSJub25lIiwNCiAgc2NhbGVfeV9kaXNjcmV0ZShsaW1pdHM9cmV2KG5hbWVzKHZlY3RfQ09HX2NhdGVnb3J5X2xvbmcpKSkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKGxpbWl0cz12ZWN0X0NPR19jYXRlZ29yeV9sb25nLCB2YWx1ZXM9Q09HX2NvbG91cnMsIGRyb3A9RkFMU0UpICsgDQogIHNjYWxlX2ZpbGxfbWFudWFsKGxpbWl0cz12ZWN0X0NPR19jYXRlZ29yeV9sb25nLCB2YWx1ZXM9Q09HX2NvbG91cnMsIGRyb3A9RkFMU0UpICsNCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEzLCAiRGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIFNEIHZzIFdOIiksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEzKSwNCiAgICAgICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNyksDQogICAgICAgICNzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE3LCBmYWNlID0gIml0YWxpYyIpLA0KICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLA0KICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAibGluZSIpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNmNGY0ZjQiKSkgKw0KICBmYWNldF9uZXN0ZWQofnRpdGxlICsgT3JnYW5pc20sIHN0cmlwID0gY3VzdG9tX3N0cmlwcywgZHJvcD1UUlVFKSAtPiBwbG90DQoNCnByaW50KHBsb3QpDQoNCmdnc2F2ZShwbG90ID0gcGxvdCwgZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9ERUdfZGF5X3ZzX25pZ2h0X2NvbW11X2JvdGhfbWV0aG9kc192ZXJ0aWNhbC50aWZmIiwgZHBpID0gMzAwLCB3aWR0aCA9IDEzLCBoZWlnaHQgPSAxMywgYmc9IndoaXRlIikNCg0KYGBgDQoNCg0KDQojIyBWZW5uIGRpYWdyYW0gb2YgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gcmVzdWx0cw0KDQpgYGB7ciB2ZW5uX2RpYWdyYW1fTVRYX2luaXRpYWwsIGVycm9yPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0PTksIGZpZy53aWR0aD05LCBmaWcuZHBpPTEwMH0NCg0KDQpsaXN0X3Zlbm4gPC0gbGlzdChyZXNfZGVzZXFfZmlsdFsocmVzX2Rlc2VxX2ZpbHQkU0FNUExFX0NPTVBBUklTT04gPT0gIjE3X1ZTXzUiKSwgImdlbmUiXSwNCiAgICAgICAgICAgICAgICAgIHJlc19tdHhfZmlsdFssICJyb3duYW1lIl0pDQoNCmludmlzaWJsZShncmlkLm5ld3BhZ2UoKSkgICANCmRyYXcucGFpcndpc2UudmVubihhcmVhMSA9IGxlbmd0aChsaXN0X3Zlbm5bWzFdXSksDQogICAgICAgICAgICAgICAgIGFyZWEyID0gbGVuZ3RoKGxpc3RfdmVubltbMl1dKSwNCiAgICAgICAgICAgICAgICAgY3Jvc3MuYXJlYSA9IGxlbmd0aChpbnRlcnNlY3QuVmVjdG9yKGxpc3RfdmVubltbMV1dLCBsaXN0X3Zlbm5bWzJdXSkpLA0KICAgICAgICAgICAgICAgICBmaWxsID0gYygiI0Q1M0Y3RiIsICIjMDM5RUJEIiksDQogICAgICAgICAgICAgICAgIGx0eSA9ICJibGFuayIsDQogICAgICAgICAgICAgICAgIGZvbnRmYW1pbHkgPSAiSGVsdmV0aWNhIiwNCiAgICAgICAgICAgICAgICAgY2V4ID0gcmVwKDIsIDMpLA0KICAgICAgICAgICAgICAgICBjYXQuY2V4ID0gcmVwKDEuNSwgMiksDQogICAgICAgICAgICAgICAgIGNhdC5wb3MgPSBjKC01MCwgNTApLA0KICAgICAgICAgICAgICAgICBjYXQuZGlzdCA9IGMoLTAuMDUsIC0wLjA1KSwNCiAgICAgICAgICAgICAgICAgY2F0LnByb21wdHMgPSBUUlVFLA0KICAgICAgICAgICAgICAgICBjYXQuY29sID0gYygiI0Q1M0Y3RiIsICIjMDM5RUJEIiksDQogICAgICAgICAgICAgICAgIGNhdC5mb250ZmFtaWx5ID0gIkhlbHZldGljYSIsDQogICAgICAgICAgICAgICAgIGNhdGVnb3J5ID0gYygiREVTZXEgIFxuYWxvbmUiLCAiTVRYTW9kZWwgIFxuY29tbXVuaXR5IiksDQogICAgICAgICAgICAgICAgIHRpdGxlID0gIkRpZmZlcmVudGlhbGx5IGFidW5kYW50IGdlbmVzIGZvdW5kIGJ5IERFU2VxMiBhbmQgTVRYbW9kZWwiLA0KICAgICAgICAgICAgICAgICBtYXJnaW4gPSAwLjEpIC0+IHZlbm5fcGxvdA0KDQoNCiMgV3JpdGluZyB0byBmaWxlDQoNCmludmlzaWJsZShwbmcoZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9WZW5uX2RpYWdyYW1fQUxERVhlMl9NVFhfREVTZXFfY29tbXVuaXR5LnBuZyIsIA0KICAgICB3aWR0aCA9IDEwMDAsIGhlaWdodCA9IDEwMDApKQ0KaW52aXNpYmxlKGdyaWQuZHJhdyh2ZW5uX3Bsb3QpKQ0KaW52aXNpYmxlKGRldi5vZmYoKSkNCmBgYA0KDQpgYGB7ciBtZXJnZV9kaWZmZXJlbnRpYWxfYW5hbHlzZXNfcmVzdWx0c30NCg0KdmVjdF9kZWdzIDwtIGFsbF9nZW5lc19maWx0ZXJlZCRnZW5lDQpjb3VudHNfY2xyX2RlZ3MgPC0gYXMubWF0cml4KGNvdW50c19jbHIpW3ZlY3RfZGVncyxdDQpgYGANCg0KDQojIyBEaWZmZXJlbnRpYWwgTWV0YWJvbGl0ZXMgaW50ZW5zaXR5DQoNCg0KYGBge3IgcHJlcGFyZV9pbnRlbnNpdHlfbWV0YUJfZGF0YX0NCg0KaWRlbnRpZmllZF9tZXRhYm9saXRlcyA8LSBsZWZ0X2pvaW4obWV0YWJvbG9taWNzX2Fubm90YXRpb25zWyxjKCJtZXRhYm9saXRlIGlkZW50aWZpY2F0aW9uIiwgIklEIildLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzX3RvX2NvbHVtbihtZXRhYm9sb21pY3NfYWxsX3RpbWVzX2ZpbHRlcmVkKSwgYnkgPSBqb2luX2J5KCJJRCIgPT0gInJvd25hbWUiKSkgICNyb3duYW1lc190b19jb2x1bW4obWV0YWJvbG9taWNzX2FsbF90aW1lc19jbHIpDQoNCmlkZW50aWZpZWRfbWV0YWJvbGl0ZXMgPC0gaWRlbnRpZmllZF9tZXRhYm9saXRlc1tpZGVudGlmaWVkX21ldGFib2xpdGVzJGBtZXRhYm9saXRlIGlkZW50aWZpY2F0aW9uYCAhPSAidW5rbm93biIsXQ0KDQpyb3cubmFtZXMoaWRlbnRpZmllZF9tZXRhYm9saXRlcykgPC0gaWRlbnRpZmllZF9tZXRhYm9saXRlcyRgbWV0YWJvbGl0ZSBpZGVudGlmaWNhdGlvbmANCg0KaWRlbnRpZmllZF9tZXRhYm9saXRlcyA8LSBpZGVudGlmaWVkX21ldGFib2xpdGVzICU+JSB0KCkgJT4lIGRhdGEuZnJhbWUoKQ0KDQoNCmlkZW50aWZpZWRfbWV0YWJvbGl0ZXMgPC0gaWRlbnRpZmllZF9tZXRhYm9saXRlc1szOm5yb3coaWRlbnRpZmllZF9tZXRhYm9saXRlcyksXSANCmlkZW50aWZpZWRfbWV0YWJvbGl0ZXMkc2FtcGxlIDwtIHJvdy5uYW1lcyhpZGVudGlmaWVkX21ldGFib2xpdGVzKQ0KDQppZGVudGlmaWVkX21ldGFib2xpdGVzIDwtIGxlZnRfam9pbihpZGVudGlmaWVkX21ldGFib2xpdGVzLCByb3duYW1lc190b19jb2x1bW4obWV0YWRhdGFfdGFibGVfbWV0YUJfYWxsX3RpbWVzKSwgYnkgPSBqb2luX2J5KCJzYW1wbGUiID09ICJyb3duYW1lIikpDQoNCmlkZW50aWZpZWRfbWV0YWJvbGl0ZXMgJT4lIHJlbmFtZSgiMi1BbWlub2JlbnpvaWMgYWNpZCIgPSAiWDIuYW1pbm9iZW56b2ljLmFjaWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiREwtTWV0aGlvbmluZSBzdWxmb3hpZGUiID0gIkRMLm1ldGhpb25pbmUuc3VsZm94aWRlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlB5cmlkb3hhbCIgPSAicHlyaWRveGFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkQtUGFudG90aGVuaWMgYWNpZCIgPSAiRC5wYW50b3RoZW5pYy5hY2lkIiAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJONi1BY2V0eWwtTC1seXNpbmUiID0gIk42LmFjZXR5bC5MLmx5c2luZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMLUdsdXRhbWljIGFjaWQiID0gIkwuZ2x1dGFtaWMuYWNpZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMLUlzb2xldWNpbmUiID0gIkwuaXNvbGV1Y2luZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCdXR5cnlsLUwtY2Fybml0aW5lIiA9ICJidXR5cnlsLkwuY2Fybml0aW5lIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFjZXR5bC1MLWNhcm5pdGluZSIgPSAiYWNldHlsLkwuY2Fybml0aW5lIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIklzb3ZhbGVyeWwtTC1jYXJuaXRpbmUiID0gImlzb3ZhbGVyeWwuTC5jYXJuaXRpbmUiKSAtPiBpZGVudGlmaWVkX21ldGFib2xpdGVzIA0KDQppZGVudGlmaWVkX21ldGFib2xpdGVzICU+JQ0KICBwaXZvdF9sb25nZXIoY29scyA9IGMoIjItQW1pbm9iZW56b2ljIGFjaWQiLCAiREwtTWV0aGlvbmluZSBzdWxmb3hpZGUiLCAiUHlyaWRveGFsIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAiRC1QYW50b3RoZW5pYyBhY2lkIiwgIk42LUFjZXR5bC1MLWx5c2luZSIsICJMLUdsdXRhbWljIGFjaWQiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICJMLUlzb2xldWNpbmUiLCAiQnV0eXJ5bC1MLWNhcm5pdGluZSIsICJBY2V0eWwtTC1jYXJuaXRpbmUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICJJc292YWxlcnlsLUwtY2Fybml0aW5lIiksIA0KICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImludGVuc2l0eSIpIC0+IGlkZW50aWZpZWRfbWV0YWJvbGl0ZXMNCiANCg0KICANCmlkZW50aWZpZWRfbWV0YWJvbGl0ZXNbaWRlbnRpZmllZF9tZXRhYm9saXRlcyR0ZW1wZXJhdHVyZSA9PSAxNyAmIGlkZW50aWZpZWRfbWV0YWJvbGl0ZXMkdGltZSA9PSAwLCAiY29uZGl0aW9uIl0gPC0gIlNEX1QwIg0KaWRlbnRpZmllZF9tZXRhYm9saXRlc1tpZGVudGlmaWVkX21ldGFib2xpdGVzJHRlbXBlcmF0dXJlID09IDUgJiBpZGVudGlmaWVkX21ldGFib2xpdGVzJHRpbWUgPT0gMCwgImNvbmRpdGlvbiJdIDwtICJXTl9UMCINCmlkZW50aWZpZWRfbWV0YWJvbGl0ZXNbaWRlbnRpZmllZF9tZXRhYm9saXRlcyR0ZW1wZXJhdHVyZSA9PSAxNyAmIGlkZW50aWZpZWRfbWV0YWJvbGl0ZXMkdGltZSA9PSAzLCAiY29uZGl0aW9uIl0gPC0gIlNEX1RGIg0KaWRlbnRpZmllZF9tZXRhYm9saXRlc1tpZGVudGlmaWVkX21ldGFib2xpdGVzJHRlbXBlcmF0dXJlID09IDUgJiBpZGVudGlmaWVkX21ldGFib2xpdGVzJHRpbWUgPT0gMywgImNvbmRpdGlvbiJdIDwtICJXTl9URiINCmlkZW50aWZpZWRfbWV0YWJvbGl0ZXNbaWRlbnRpZmllZF9tZXRhYm9saXRlcyR0ZW1wZXJhdHVyZSA9PSAxNywgImZpbGwiXSA8LSAiI0Y4QUQxOCINCmlkZW50aWZpZWRfbWV0YWJvbGl0ZXNbaWRlbnRpZmllZF9tZXRhYm9saXRlcyR0ZW1wZXJhdHVyZSA9PSA1LCAiZmlsbCJdIDwtICIjODlEREY4Ig0KaWRlbnRpZmllZF9tZXRhYm9saXRlc1tpZGVudGlmaWVkX21ldGFib2xpdGVzJHRlbXBlcmF0dXJlID09IDE3LCAiY29sb3VyIl0gPC0gIiNiMDc5MGIiDQppZGVudGlmaWVkX21ldGFib2xpdGVzW2lkZW50aWZpZWRfbWV0YWJvbGl0ZXMkdGVtcGVyYXR1cmUgPT0gNSwgImNvbG91ciJdIDwtICIjMWFhN2Q0Ig0KDQppZGVudGlmaWVkX21ldGFib2xpdGVzJGludGVuc2l0eSA8LSBhcy5udW1lcmljKGlkZW50aWZpZWRfbWV0YWJvbGl0ZXMkaW50ZW5zaXR5KQ0KDQoNCg0KYGBgDQoNCg0KIyMjIE1ldGFib2xpdGVzIG1vcmUgYWJ1bmRhbnQgaW4gV04NCg0KYGBge3IgaW50ZW5zaXR5X21ldGFCX1dOfQ0KDQogIA0KDQppZGVudGlmaWVkX21ldGFib2xpdGVzICU+JSANCiAgZmlsdGVyKG5hbWUgJWluJSBjKCIyLUFtaW5vYmVuem9pYyBhY2lkIiwgIkwtR2x1dGFtaWMgYWNpZCIsDQogICAgICAgICAgICAgICAgICAgICAiREwtTWV0aGlvbmluZSBzdWxmb3hpZGUiLCAiTjYtQWNldHlsLUwtbHlzaW5lIiwNCiAgICAgICAgICAgICAgICAgICAgICJELVBhbnRvdGhlbmljIGFjaWQiLCAiUHlyaWRveGFsIiApKSAlPiUNCiAgZmlsdGVyKGNvbmRpdGlvbiAlaW4lIGMoIlNEX1RGIiwgIldOX1RGIikpICU+JQ0KICBnZ3Bsb3QoYWVzKHk9aW50ZW5zaXR5LCB4PWNvbmRpdGlvbiwgZ3JvdXA9Y29uZGl0aW9uKSkgKw0KICBnZW9tX2JveHBsb3QoYWVzKGZpbGw9ZmlsbCwgY29sb3VyPWNvbG91cikpICsNCiAgc2NhbGVfZmlsbF9pZGVudGl0eSgpICsNCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkoKSArDQogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZT0xMiksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZnVuY3Rpb24oeCkgZm9ybWF0KHgsIHNjaWVudGlmaWMgPSBUUlVFKSwgbGltaXRzID0gYygwLE5BKSwgYnJlYWtzID0gZXh0ZW5kZWRfYnJlYWtzKG49NSkpICsNCiAgZmFjZXRfd3JhcCh+bmFtZSwgc2NhbGU9ImZyZWUiLCBuY29sPTIpIC0+IHBsb3Rfd24NCg0KDQpwcmludChwbG90X3duKQ0KDQpnZ3NhdmUocGxvdCA9IHBsb3Rfd24sIGZpbGVuYW1lID0gIi4uL2ZpZ3VyZXMvbWV0YWJvbGl0ZXNfV04udGlmZiIsIGRwaSA9IDMwMCwgd2lkdGggPSA4LCBoZWlnaHQgPSA2LCBiZz0id2hpdGUiKQ0KDQoNCmBgYA0KDQoNCiMjIyBNZXRhYm9saXRlcyBtb3JlIGFidW5kYW50IGluIFNEDQoNCmBgYHtyIGludGVuc2l0eV9tZXRhQl9TRH0NCg0KDQoNCmlkZW50aWZpZWRfbWV0YWJvbGl0ZXMgJT4lIGZpbHRlcihuYW1lICVpbiUgYygiTC1Jc29sZXVjaW5lIiwgIkFjZXR5bC1MLWNhcm5pdGluZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQnV0eXJ5bC1MLWNhcm5pdGluZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSXNvdmFsZXJ5bC1MLWNhcm5pdGluZSIpKSAlPiUNCiAgZmlsdGVyKGNvbmRpdGlvbiAlaW4lIGMoIlNEX1RGIiwgIldOX1RGIikpICU+JQ0KICBnZ3Bsb3QoYWVzKHk9aW50ZW5zaXR5LCB4PWNvbmRpdGlvbiwgZ3JvdXA9Y29uZGl0aW9uKSkgKw0KICBnZW9tX2JveHBsb3QoYWVzKGZpbGw9ZmlsbCwgY29sb3VyPWNvbG91cikpICsNCiAgc2NhbGVfZmlsbF9pZGVudGl0eSgpICsNCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkoKSArDQogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZT0xMiksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZnVuY3Rpb24oeCkgZm9ybWF0KHgsIHNjaWVudGlmaWMgPSBUUlVFKSwgbGltaXRzID0gYygwLE5BKSwgYnJlYWtzID0gZXh0ZW5kZWRfYnJlYWtzKG49NSkpICsNCiAgZmFjZXRfd3JhcCh+bmFtZSwgc2NhbGU9ImZyZWUiLCBuY29sPTIpIC0+IHBsb3Rfc2QNCg0KcHJpbnQocGxvdF9zZCkNCg0KZ2dzYXZlKHBsb3QgPSBwbG90X3NkLCBmaWxlbmFtZSA9ICIuLi9maWd1cmVzL21ldGFib2xpdGVzX1NELnRpZmYiLCBkcGkgPSAzMDAsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNCwgYmc9IndoaXRlIikNCg0KDQpgYGANCg0KDQojIyMgU2Vzc2lvbiBpbmZvcm1hdGlvbnMNCg0KYGBge3IgU2Vzc2lvbl9pbmZvfQ0Kc2Vzc2lvbkluZm8oKQ0KYGBgDQo=